buffer_pool: add F001 regression tests
Three unit tests for the BufferPool zero-fill fix: 1. recycled_buffer_is_fully_zeroed_after_shrink: writes a 'secret', truncates to 8 bytes, drops to recycle, verifies the entire recycled buffer is zero. Catches the original v.fill(0)+set_len regression where the tail bytes were uninitialized. 2. recycled_buffer_zeroed_at_known_nonzero_size: writes 0xAB across the full buffer, truncates, recycles, verifies all bytes are 0. Catches the same regression from a different angle. 3. fresh_buffer_is_zeroed: trivial check that a brand-new buffer from a fresh pool is already zeroed (sanity check). The netstack crate is redox-target-only (cannot run on host due to redox_syscall/redox-scheme dependencies), but these tests serve as documentation of the expected behavior and can run in the canonical build-redbear.sh target test pass.
This commit is contained in:
@@ -104,3 +104,64 @@ impl BufferPool {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::io::Write;
|
||||
|
||||
#[test]
|
||||
fn recycled_buffer_is_fully_zeroed_after_shrink() {
|
||||
// Regression test for the F001 information-disclosure fix:
|
||||
// a recycled buffer must be fully zeroed across its entire
|
||||
// capacity, including the part that was previously a
|
||||
// shorter logical length (the shrink-then-recycle path that
|
||||
// originally leaked stale packet data into the new flow).
|
||||
let mut pool = BufferPool::new(256);
|
||||
|
||||
// Round 1: write a "secret" then shrink.
|
||||
let mut buf = pool.get_buffer();
|
||||
buf.as_mut_slice()
|
||||
.write_all(b"top secret password: hunter2")
|
||||
.unwrap();
|
||||
buf.as_mut_slice().truncate(8);
|
||||
|
||||
// Recycle.
|
||||
drop(buf);
|
||||
let buf = pool.get_buffer();
|
||||
|
||||
// Round 2: every byte must be zero.
|
||||
let zeros = buf.as_ref().iter().all(|&b| b == 0);
|
||||
assert!(zeros, "recycled buffer is not fully zeroed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recycled_buffer_zeroed_at_known_nonzero_size() {
|
||||
// Make sure a recycled buffer that was previously written
|
||||
// with nonzero data and resized to 8 bytes still shows all
|
||||
// zeros across its new capacity. This catches the previous
|
||||
// v.fill(0) + set_len(capacity) implementation that only zeroed
|
||||
// the old logical length.
|
||||
let mut pool = BufferPool::new(64);
|
||||
|
||||
let mut buf = pool.get_buffer();
|
||||
for i in 0..buf.as_ref().len() {
|
||||
buf.as_mut_slice()[i] = 0xAB;
|
||||
}
|
||||
buf.as_mut_slice().truncate(32);
|
||||
|
||||
drop(buf);
|
||||
let buf = pool.get_buffer();
|
||||
for i in 0..buf.as_ref().len() {
|
||||
assert_eq!(buf.as_ref()[i], 0, "byte {i} not zeroed");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fresh_buffer_is_zeroed() {
|
||||
// First use of a buffer from a fresh pool must be all-zero.
|
||||
let mut pool = BufferPool::new(128);
|
||||
let buf = pool.get_buffer();
|
||||
assert!(buf.as_ref().iter().all(|&b| b == 0));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user