Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable decoding into buffer without extra space in it #14

Merged
merged 1 commit into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion fuzz/fuzz_targets/inflate_bytewise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ fuzz_target!(|input: (u8, Vec<u8>)| {
let mut decoder = fdeflate::Decompressor::new();
loop {
let output_position = decompressed.len();
decompressed.push(1);
if output_position < data.len() {
decompressed.push(1);
}

let (consumed, produced) = decoder
.read(
Expand Down
67 changes: 61 additions & 6 deletions src/decompress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,12 +578,11 @@ impl Decompressor {
mut output_index: usize,
) -> Result<usize, DecompressionError> {
while let State::CompressedData = self.state {
self.fill_buffer(remaining_input);
if output_index == output.len() {
break;
}

self.fill_buffer(remaining_input);

let mut bits = self.buffer;
let litlen_entry = self.compression.litlen_table[(bits & 0xfff) as usize];
let litlen_code_bits = litlen_entry as u8;
Expand Down Expand Up @@ -848,13 +847,12 @@ impl Decompressor {
///
/// When this function returns `Ok`, at least one of the following is true:
/// - The input is fully consumed.
/// - The output is full.
/// - The output is full but there are more bytes to output.
/// - The deflate stream is complete (and `is_done` will return true).
///
/// # Panics
///
/// This function will panic if there is no space in `output` beyond index `output_position` or
/// if `output_position` is out of bounds.
/// This function will panic if `output_position` is out of bounds.
pub fn read(
&mut self,
input: &[u8],
Expand All @@ -866,7 +864,7 @@ impl Decompressor {
return Ok((0, 0));
}

assert!(output.len() > output_position);
assert!(output_position <= output.len());

let mut remaining_input = input;
let mut output_index = output_position;
Expand Down Expand Up @@ -1176,4 +1174,61 @@ mod tests {
.1;
assert_eq!(&decompressed[..decompressed_len], b"Hello world!");
}

#[test]
fn checksum_after_eof() {
let input = b"Hello world!";
let compressed = crate::compress_to_vec(input);

let mut decompressor = Decompressor::new();
let mut decompressed = vec![0; 1024];
let (input_consumed, output_written) = decompressor
.read(
&compressed[..compressed.len() - 1],
&mut decompressed,
0,
false,
)
.unwrap();
assert_eq!(output_written, input.len());
assert_eq!(input_consumed, compressed.len() - 1);

let (input_consumed, output_written) = decompressor
.read(
&compressed[input_consumed..],
&mut decompressed[..output_written],
output_written,
true,
)
.unwrap();
assert!(decompressor.is_done());
assert_eq!(input_consumed, 1);
assert_eq!(output_written, 0);

assert_eq!(&decompressed[..input.len()], input);
}

#[test]
fn zero_length() {
let mut compressed = crate::compress_to_vec(b"").to_vec();

// Splice in zero-length non-compressed blocks.
for _ in 0..10 {
println!("compressed len: {}", compressed.len());
compressed.splice(2..2, [0u8, 0, 0, 0xff, 0xff].into_iter());
}

// Ensure that the full input is decompressed, regardless of whether
// `end_of_input` is set.
for end_of_input in [true, false] {
let mut decompressor = Decompressor::new();
let (input_consumed, output_written) = decompressor
.read(&compressed, &mut [], 0, end_of_input)
.unwrap();

assert!(decompressor.is_done());
assert_eq!(input_consumed, compressed.len());
assert_eq!(output_written, 0);
}
}
}
Loading