Skip to content

Commit 773b7c5

Browse files
committed
Add regression test for byte-pool bug breaking ensure_capacity()
1 parent ba338e3 commit 773b7c5

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

src/imap_stream.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ impl Buffer {
183183
let increase = std::cmp::max(Buffer::BLOCK_SIZE, extra_bytes_needed);
184184
self.grow(increase)?;
185185
}
186+
187+
// Assert that the buffer at least one free byte.
188+
debug_assert!(self.offset < self.block.size());
186189
Ok(())
187190
}
188191

@@ -386,6 +389,35 @@ mod tests {
386389
assert_eq!(buf.block.size(), 3 * Buffer::BLOCK_SIZE);
387390
}
388391

392+
/// Regression test for a bug in ensure_capacity() caused
393+
/// by a bug in byte-pool crate 0.2.2 dependency.
394+
///
395+
/// ensure_capacity() sometimes did not ensure that
396+
/// at least one byte is available, which in turn
397+
/// resulted in attempt to read into a buffer of zero size.
398+
/// When poll_read() reads into a buffer of zero size,
399+
/// it can only read zero bytes, which is indistinguishable
400+
/// from EOF and resulted in an erroneous detection of EOF
401+
/// when in fact the stream was not closed.
402+
#[test]
403+
fn test_ensure_capacity_loop() {
404+
let mut buf = Buffer::new();
405+
406+
for i in 1..500 {
407+
// Ask for `i` bytes.
408+
buf.ensure_capacity(i).unwrap();
409+
410+
// Test that we can read at least as much as requested.
411+
let free = buf.free_as_mut_slice();
412+
let used = free.len();
413+
assert!(used >= i);
414+
drop(free);
415+
416+
// Use as much as allowed.
417+
buf.extend_used(used);
418+
}
419+
}
420+
389421
#[test]
390422
fn test_buffer_take_and_return_block() {
391423
// This test identifies blocks by their size.

0 commit comments

Comments
 (0)