From 35454de390b28c4becb90067c0020537d4e3b5de Mon Sep 17 00:00:00 2001 From: Patrick Marks Date: Thu, 26 Sep 2024 11:30:29 +0200 Subject: [PATCH 1/2] make sure to exhaust any un-read bytes held within lz4 context --- src/decoder.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/decoder.rs b/src/decoder.rs index c13e3b1c3..9cf3e49fa 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -69,13 +69,13 @@ impl Read for Decoder { self.next }; self.len = self.r.read(&mut self.buf[0..need])?; - if self.len == 0 { - break; - } + // NOTE: we do not exit here if there was nothing read + // The lz4 context may still have more bytes to emit. + self.pos = 0; self.next -= self.len; } - while (dst_offset < buf.len()) && (self.pos < self.len) { + while (dst_offset < buf.len()) && ((self.pos < self.len) || self.len == 0) { let mut src_size = (self.len - self.pos) as size_t; let mut dst_size = (buf.len() - dst_offset) as size_t; let len = check_error(unsafe { @@ -90,6 +90,14 @@ impl Read for Decoder { })?; self.pos += src_size as usize; dst_offset += dst_size as usize; + + // We need to keep trying to read bytes from the decompressor + // until it is no longer emitting them, even after it + // has finished reading bytes. + if dst_size == 0 && src_size == 0 { + return Ok(dst_offset); + } + if len == 0 { self.next = 0; return Ok(dst_offset); @@ -290,6 +298,42 @@ mod test { finish_decode(decoder); } + /// Ensure that we emit the full decompressed stream even if we're + /// using a very small output buffer. + #[test] + fn issue_45() { + // create an encoder + let mut enc = crate::EncoderBuilder::new() + .build(Vec::new()).unwrap(); + + // write 'a' 100 times to the encoder + let text: Vec = vec!['a' as u8; 100]; + enc.write_all(&text[..]).unwrap(); + + // flush the encoder + enc.flush().unwrap(); + + + // read from the decoder, buf_size bytes at a time + for buf_size in [5, 10, 15, 20, 25] { + let mut buf = vec![0; buf_size]; + + let mut total_bytes_read = 0; + + // create a decoder wrapping the backing buffer + let mut dec = crate::Decoder::new(&enc.writer()[..]).unwrap(); + while let Ok(n) = dec.read(&mut buf[..]) { + if n == 0 { + break; + } + + total_bytes_read += n; + } + + assert_eq!(total_bytes_read, text.len()); + } + } + fn random() -> StdRng { let seed: [u8; 32] = [ 157, 164, 190, 237, 231, 103, 60, 22, 197, 108, 51, 176, 30, 170, 155, 21, 163, 249, From 4f59e42dc760b5adc79fa8c5fb775e66b599bdd3 Mon Sep 17 00:00:00 2001 From: Patrick Marks Date: Thu, 26 Sep 2024 11:31:37 +0200 Subject: [PATCH 2/2] fmt --- src/decoder.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/decoder.rs b/src/decoder.rs index 9cf3e49fa..f35af43dc 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -92,7 +92,7 @@ impl Read for Decoder { dst_offset += dst_size as usize; // We need to keep trying to read bytes from the decompressor - // until it is no longer emitting them, even after it + // until it is no longer emitting them, even after it // has finished reading bytes. if dst_size == 0 && src_size == 0 { return Ok(dst_offset); @@ -303,8 +303,7 @@ mod test { #[test] fn issue_45() { // create an encoder - let mut enc = crate::EncoderBuilder::new() - .build(Vec::new()).unwrap(); + let mut enc = crate::EncoderBuilder::new().build(Vec::new()).unwrap(); // write 'a' 100 times to the encoder let text: Vec = vec!['a' as u8; 100]; @@ -313,7 +312,6 @@ mod test { // flush the encoder enc.flush().unwrap(); - // read from the decoder, buf_size bytes at a time for buf_size in [5, 10, 15, 20, 25] { let mut buf = vec![0; buf_size]; @@ -326,7 +324,7 @@ mod test { if n == 0 { break; } - + total_bytes_read += n; }