Skip to content

Commit e0d5920

Browse files
committed
test: adds sysex insert fuzz test
1 parent d43aff7 commit e0d5920

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

fuzz/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ cargo-fuzz = true
99

1010
[dependencies]
1111
libfuzzer-sys = "0.4"
12+
arbitrary = { version = "1.0", features = [
13+
"derive",
14+
] }
15+
rand = "0.9.1"
1216

1317
[dependencies.midi2]
1418
path = "../midi2"
@@ -32,3 +36,10 @@ path = "./fuzz_targets/sysex7_payload_roundtrip.rs"
3236
test = false
3337
doc = false
3438
bench = false
39+
40+
[[bin]]
41+
name = "generic_sysex_inserting_payloads"
42+
path = "./fuzz_targets/generic_sysex_inserting_payloads.rs"
43+
test = false
44+
doc = false
45+
bench = false
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#![no_main]
2+
3+
use libfuzzer_sys::fuzz_target;
4+
use midi2::Sysex;
5+
use rand::{Rng, SeedableRng};
6+
7+
struct FixedSizeBuffer<U: midi2::buffer::Unit>(Vec<U>);
8+
9+
impl<U: midi2::buffer::Unit> midi2::buffer::Buffer for FixedSizeBuffer<U> {
10+
type Unit = U;
11+
fn buffer(&self) -> &[Self::Unit] {
12+
&self.0
13+
}
14+
}
15+
16+
impl<U: midi2::buffer::Unit> midi2::buffer::BufferMut for FixedSizeBuffer<U> {
17+
fn buffer_mut(&mut self) -> &mut [Self::Unit] {
18+
&mut self.0
19+
}
20+
}
21+
22+
impl<U: midi2::buffer::Unit> midi2::buffer::BufferTryResize for FixedSizeBuffer<U> {
23+
fn try_resize(&mut self, new_size: usize) -> Result<(), midi2::error::BufferOverflow> {
24+
if new_size > self.0.len() {
25+
return Err(midi2::error::BufferOverflow);
26+
}
27+
Ok(())
28+
}
29+
}
30+
31+
impl<U: midi2::buffer::Unit> FixedSizeBuffer<U> {
32+
fn new(size: usize) -> Self {
33+
Self(std::iter::repeat_n(U::zero(), size).collect())
34+
}
35+
}
36+
37+
#[derive(arbitrary::Arbitrary, Debug)]
38+
struct InputData {
39+
seed: u64,
40+
initial_data: Vec<u8>,
41+
data_to_insert: Vec<u8>,
42+
}
43+
44+
const MAX_BUFFER_SIZE: usize = 1024;
45+
46+
trait IntoByte<B> {
47+
fn byte(&self) -> B;
48+
}
49+
50+
impl IntoByte<midi2::ux::u7> for u8 {
51+
fn byte(&self) -> midi2::ux::u7 {
52+
midi2::num::u7::new(self & 0x7F)
53+
}
54+
}
55+
56+
impl IntoByte<u8> for u8 {
57+
fn byte(&self) -> u8 {
58+
*self
59+
}
60+
}
61+
62+
fn test_case<B, M>(data: &InputData, mut message: M, index: usize)
63+
where
64+
B: midi2::buffer::Buffer + midi2::buffer::BufferTryResize + midi2::buffer::BufferMut,
65+
M: midi2::Sysex<B>,
66+
<M as Sysex<B>>::Byte: Eq + core::fmt::Debug,
67+
u8: IntoByte<<M as Sysex<B>>::Byte>,
68+
{
69+
let Ok(()) = message.try_set_payload(data.initial_data.iter().map(u8::byte)) else {
70+
return;
71+
};
72+
73+
{
74+
let initial = message.payload().collect::<Vec<_>>();
75+
assert_eq!(
76+
initial,
77+
data.initial_data.iter().map(u8::byte).collect::<Vec<_>>()
78+
);
79+
}
80+
81+
let Ok(()) = message.try_insert_payload(data.data_to_insert.iter().map(u8::byte), index) else {
82+
return;
83+
};
84+
85+
let actual = message.payload().collect::<Vec<_>>();
86+
let expected = {
87+
let mut ret = data.initial_data.clone();
88+
ret.splice(index..index, data.data_to_insert.clone());
89+
ret.iter().map(u8::byte).collect::<Vec<_>>()
90+
};
91+
assert_eq!(actual, expected);
92+
}
93+
94+
fuzz_target!(|data: InputData| {
95+
let mut rng = rand::rngs::StdRng::seed_from_u64(data.seed);
96+
let fized_size_buffer_size = rng.random_range(4..MAX_BUFFER_SIZE);
97+
let index = if data.initial_data.is_empty() {
98+
0
99+
} else {
100+
rng.random_range(0..data.initial_data.len())
101+
};
102+
test_case(
103+
&data,
104+
midi2::sysex8::Sysex8::<FixedSizeBuffer<u32>>::try_new_with_buffer(
105+
FixedSizeBuffer::<u32>::new(fized_size_buffer_size),
106+
)
107+
.unwrap(),
108+
index,
109+
);
110+
test_case(
111+
&data,
112+
midi2::sysex7::Sysex7::<FixedSizeBuffer<u32>>::try_new_with_buffer(
113+
FixedSizeBuffer::<u32>::new(fized_size_buffer_size),
114+
)
115+
.unwrap(),
116+
index,
117+
);
118+
test_case(
119+
&data,
120+
midi2::sysex7::Sysex7::<FixedSizeBuffer<u8>>::try_new_with_buffer(
121+
FixedSizeBuffer::<u8>::new(fized_size_buffer_size),
122+
)
123+
.unwrap(),
124+
index,
125+
);
126+
});

0 commit comments

Comments
 (0)