Skip to content

Commit 3ae7ad6

Browse files
committed
Add a test demonstrating underread of underlying buffers
When reading from a decompressor that was constructed using `Decoder::with_buffer`, the decoder may not consume all of the input by the time it returns all of the decompressed output. This means when you call `.finish()` on the decoder to get the underlying stream back, it is not pointing after the end of the compressed data. This commit adds a test that demonstrates the issue.
1 parent 92f87dc commit 3ae7ad6

2 files changed

Lines changed: 38 additions & 0 deletions

File tree

assets/zeros64.zst

21 Bytes
Binary file not shown.

tests/issue_n.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use std::io::Read;
2+
3+
#[test]
4+
fn test_issue_n() {
5+
// This is 64 compressed zero bytes.
6+
let compressed_data = include_bytes!("../assets/zeros64.zst");
7+
let decompressed_size = 64;
8+
9+
// Construct a decompressor using `with_buffer`. This should be ok as
10+
// `Cursor` is `BufRead`.
11+
let reader = std::io::Cursor::new(compressed_data);
12+
let mut decomp = zstd::Decoder::with_buffer(reader).unwrap();
13+
14+
// Count how many bytes we decompress.
15+
let mut total = 0;
16+
17+
// Decompress four bytes at a time (this is necessary to trigger underrun
18+
// behaviour).
19+
for _ in 0..(decompressed_size / 4) {
20+
let mut buf = [0u8; 4];
21+
let count = decomp.read(&mut buf).unwrap();
22+
total += count;
23+
}
24+
25+
// Finish reading and get the buffer back.
26+
let reader = decomp.finish();
27+
28+
// The cursor should now be at the end of the compressed data.
29+
println!("We read {total}/{decompressed_size} decompressed bytes");
30+
println!(
31+
"The underlying cursor is at position {} of {} compressed bytes",
32+
reader.position(),
33+
compressed_data.len()
34+
);
35+
36+
assert_eq!(total, decompressed_size);
37+
assert_eq!(reader.position() as usize, compressed_data.len());
38+
}

0 commit comments

Comments
 (0)