-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- fixes bug which caused long queues to behave strangely. - fixes memory leak for `ByteData` wrapped `SharedBytes` or externals. - add a couple of fuzzing tests
- Loading branch information
Showing
25 changed files
with
824 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
target | ||
corpus | ||
artifacts | ||
coverage |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
[package] | ||
name = "bytedata-fuzz" | ||
version = "0.0.0" | ||
publish = false | ||
edition = "2021" | ||
|
||
[package.metadata] | ||
cargo-fuzz = true | ||
|
||
[dependencies] | ||
libfuzzer-sys = "=0.4.7" | ||
|
||
[dependencies.bytedata] | ||
path = ".." | ||
features = ["arbitrary_1", "alloc", "std", "queue"] | ||
|
||
[[bin]] | ||
name = "bytedata" | ||
path = "fuzz_targets/bytedata.rs" | ||
test = false | ||
doc = false | ||
bench = false | ||
|
||
[[bin]] | ||
name = "bytequeue" | ||
path = "fuzz_targets/bytequeue.rs" | ||
test = false | ||
doc = false | ||
bench = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#![no_main] | ||
|
||
use libfuzzer_sys::fuzz_target; | ||
|
||
use bytedata::ByteData; | ||
|
||
fuzz_target!(|input: ByteData| { | ||
let full_len = input.len(); | ||
let owned = input.as_slice().to_vec(); | ||
assert_eq!(owned.len(), full_len); | ||
let mut cloned_data = input.clone(); | ||
assert_eq!(cloned_data.len(), full_len); | ||
let mut sliced_data = input.sliced(0..full_len); | ||
assert_eq!(sliced_data.len(), full_len); | ||
let fst_byte = input.first().copied(); | ||
let lst_byte = input.as_slice().last().copied(); | ||
assert_eq!(fst_byte, sliced_data.first().copied()); | ||
assert_eq!(lst_byte, sliced_data.as_slice().last().copied()); | ||
assert_eq!(fst_byte, owned.first().copied()); | ||
assert_eq!(lst_byte, owned.last().copied()); | ||
|
||
if !input.is_empty() { | ||
let mut sliced_data = input.sliced(0..1); | ||
assert_eq!(fst_byte, sliced_data.first().copied()); | ||
assert_eq!(fst_byte, sliced_data.last()); | ||
let mut sliced_data = input.sliced(full_len - 1..full_len); | ||
assert_eq!(lst_byte, sliced_data.first().copied()); | ||
assert_eq!(lst_byte, sliced_data.last()); | ||
} | ||
|
||
let mut owned_iter = owned.into_iter(); | ||
let mut input_iter = input.iter(); | ||
loop { | ||
match (owned_iter.next(), input_iter.next()) { | ||
(Some(owned_byte), Some(input_byte)) => { | ||
assert_eq!(owned_byte, *input_byte); | ||
} | ||
(None, None) => { | ||
break; | ||
} | ||
_ => { | ||
panic!("Different lengths"); | ||
} | ||
} | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
#![no_main] | ||
|
||
use libfuzzer_sys::{fuzz_target, arbitrary::{Arbitrary, Unstructured}}; | ||
|
||
use bytedata::ByteQueue; | ||
|
||
fn is_same_as(data: &[u8], queue: &ByteQueue) -> bool { | ||
let mut offs = 0; | ||
for chunk in queue.chunks() { | ||
if chunk.as_slice() != &data[offs..offs + chunk.len()] { | ||
return false; | ||
} | ||
offs += chunk.len(); | ||
} | ||
offs == data.len() | ||
} | ||
|
||
fuzz_target!(|input: &[u8]| { | ||
let uns = Unstructured::new(input); | ||
let mut queue = <ByteQueue as Arbitrary>::arbitrary_take_rest(uns).unwrap(); | ||
let static_ref_data: Vec<u8> = queue.bytes().collect(); | ||
assert_eq!(queue.len(), static_ref_data.len()); | ||
if queue.is_empty() { | ||
return; | ||
} | ||
if !is_same_as(&static_ref_data, &queue) { | ||
let ref_data = bytedata::ByteStringRender::from_slice(&static_ref_data); | ||
panic!("queue is not the same as the input data (from start)\r\n queue: {queue:?}\r\n ref_data: {ref_data:?}"); | ||
} | ||
let mut ref_data = static_ref_data.clone(); | ||
|
||
{ | ||
let mut chunks = Vec::with_capacity(queue.chunk_len()); | ||
for chunk in queue.chunks() { | ||
chunks.push(chunk.len()); | ||
} | ||
let end = queue.len() - 1; | ||
let end_byte = queue.split_off(end); | ||
assert_eq!(end_byte.len(), 1); | ||
assert_eq!(queue.len(), end); | ||
queue.push_back(end_byte); | ||
assert_eq!(queue.len(), end + 1); | ||
|
||
if !is_same_as(&ref_data, &queue) { | ||
let ref_data = bytedata::ByteStringRender::from_slice(&ref_data); | ||
panic!("queue is not the same as the input data (after re-push)\r\n queue: {queue:?}\r\n ref_data: {ref_data:?}\r\n chunks: {chunks:?}"); | ||
} | ||
} | ||
|
||
{ | ||
queue.push_front(b"test".as_ref()); | ||
assert_eq!(queue.len(), ref_data.len() + 4); | ||
_ = queue.drain(0..5); | ||
assert_eq!(queue.len(), ref_data.len() - 1); | ||
let len = ref_data.len(); | ||
core::mem::drop(ref_data.drain(..1)); | ||
|
||
if !is_same_as(&ref_data, &queue) { | ||
let ref_data = bytedata::ByteStringRender::from_slice(&ref_data); | ||
panic!("queue is not the same as the input data (after push-drain)\r\n queue: {queue:?}\r\n ref_data: {ref_data:?}"); | ||
} | ||
|
||
let mut dr = ref_data.drain(..); | ||
let mut n = 0; | ||
let mut dr2 = queue.drain(..); | ||
while let Some(b) = dr2.next() { | ||
n += 1; | ||
let ref_b = dr.next().unwrap(); | ||
if b != ref_b { | ||
let dr = dr.collect::<Vec<u8>>(); | ||
let dr2 = dr2.collect::<Vec<u8>>(); | ||
let part0 = &static_ref_data[..n]; | ||
let ref_data = [part0, core::slice::from_ref(&ref_b), &dr]; | ||
let ref_data = bytedata::MultiByteStringRender::new(&ref_data); | ||
let queue = [part0, core::slice::from_ref(&b), &dr2]; | ||
let queue = bytedata::MultiByteStringRender::new(&queue); | ||
panic!("byte {n}/{len} differs, {b} != {ref_b}\r\n queue: {queue:?}\r\n ref_data: {ref_data:?}"); | ||
return; | ||
} | ||
} | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use arbitrary_1::{Arbitrary, Error, Unstructured}; | ||
|
||
use crate::{ByteData, ByteQueue}; | ||
|
||
#[cfg_attr(docsrs, doc(cfg(feature = "queue")))] | ||
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary_1")))] | ||
impl<'a> Arbitrary<'a> for ByteQueue<'a> { | ||
#[allow( | ||
clippy::missing_inline_in_public_items, | ||
clippy::unwrap_in_result, | ||
clippy::min_ident_chars | ||
)] | ||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, Error> { | ||
let mut buffer = Self::new(); | ||
let mut maxlen = u.arbitrary_len::<ByteData<'a>>()?; | ||
while !u.is_empty() && maxlen != 0 { | ||
let data = u.arbitrary::<ByteData<'a>>()?; | ||
maxlen -= 1; | ||
let dir = u.arbitrary::<bool>().unwrap_or_default(); | ||
if dir { | ||
buffer.push_front(data); | ||
} else { | ||
buffer.push_back(data); | ||
} | ||
} | ||
Ok(buffer) | ||
} | ||
|
||
#[allow( | ||
clippy::missing_inline_in_public_items, | ||
clippy::unwrap_in_result, | ||
clippy::min_ident_chars | ||
)] | ||
fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result<Self, Error> { | ||
let mut buffer = Self::new(); | ||
while !u.is_empty() { | ||
let data = u.arbitrary::<ByteData<'a>>()?; | ||
let dir = u.arbitrary::<bool>().unwrap_or_default(); | ||
if dir { | ||
buffer.push_front(data); | ||
} else { | ||
buffer.push_back(data); | ||
} | ||
} | ||
Ok(buffer) | ||
} | ||
} |
Oops, something went wrong.