Merge tag 'v1.11.1'

This commit is contained in:
Alice Ryhl
2026-02-03 13:45:19 +00:00
5 changed files with 33 additions and 9 deletions
+4
View File
@@ -1,3 +1,7 @@
# 1.11.1 (February 3rd, 2026)
- Fix integer overflow in `BytesMut::reserve`
# 1.11.0 (November 14th, 2025)
- Bump MSRV to 1.57 (#788)
+1 -1
View File
@@ -4,7 +4,7 @@ name = "bytes"
# When releasing to crates.io:
# - Update CHANGELOG.md.
# - Create "v1.x.y" git tag.
version = "1.11.0"
version = "1.11.1"
edition = "2021"
rust-version = "1.57"
license = "MIT"
+3
View File
@@ -8,3 +8,6 @@ export MIRIFLAGS="-Zmiri-strict-provenance"
cargo miri test
cargo miri test --target mips64-unknown-linux-gnuabi64
# run with wrapping integer overflow instead of panic
cargo miri test --release
+12 -8
View File
@@ -697,9 +697,15 @@ impl BytesMut {
let offset = self.ptr.as_ptr().offset_from(ptr) as usize;
let new_cap_plus_offset = match new_cap.checked_add(offset) {
Some(new_cap_plus_offset) => new_cap_plus_offset,
None if !allocate => return false,
None => panic!("overflow"),
};
// Compare the condition in the `kind == KIND_VEC` case above
// for more details.
if v_capacity >= new_cap + offset {
if v_capacity >= new_cap_plus_offset {
self.cap = new_cap;
// no copy is necessary
} else if v_capacity >= new_cap && offset >= len {
@@ -715,14 +721,12 @@ impl BytesMut {
if !allocate {
return false;
}
// calculate offset
let off = (self.ptr.as_ptr() as usize) - (v.as_ptr() as usize);
// new_cap is calculated in terms of `BytesMut`, not the underlying
// `Vec`, so it does not take the offset into account.
//
// Thus we have to manually add it here.
new_cap = new_cap.checked_add(off).expect("overflow");
new_cap = new_cap_plus_offset;
// The vector capacity is not sufficient. The reserve request is
// asking for more than the initial buffer capacity. Allocate more
@@ -744,13 +748,13 @@ impl BytesMut {
// the unused capacity of the vector is copied over to the new
// allocation, so we need to ensure that we don't have any data we
// care about in the unused capacity before calling `reserve`.
debug_assert!(off + len <= v.capacity());
v.set_len(off + len);
debug_assert!(offset + len <= v.capacity());
v.set_len(offset + len);
v.reserve(new_cap - v.len());
// Update the info
self.ptr = vptr(v.as_mut_ptr().add(off));
self.cap = v.capacity() - off;
self.ptr = vptr(v.as_mut_ptr().add(offset));
self.cap = v.capacity() - offset;
}
return true;
+13
View File
@@ -1707,3 +1707,16 @@ fn bytes_mut_put_bytes_specialization() {
// If allocation is reused, capacity should be equal to original vec capacity.
assert_eq!(bytes_mut.capacity(), capacity);
}
#[test]
#[should_panic]
fn bytes_mut_reserve_overflow() {
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');
}