Skip to content

Commit a35a151

Browse files
authored
Fix integer overflow in BlobVec::reserve_exact (#11234)
# Objective When `BlobVec::reserve` is called with an argument causing capacity overflow, in release build capacity overflow is ignored, and capacity is decreased. I'm not sure it is possible to exploit this issue using public API of `bevy_ecs`, but better fix it anyway. ## Solution Check for capacity overflow.
1 parent 425570a commit a35a151

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

crates/bevy_ecs/src/storage/blob_vec.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,10 @@ impl BlobVec {
132132
/// For ZST it panics unconditionally because ZST `BlobVec` capacity
133133
/// is initialized to `usize::MAX` and always stays that way.
134134
fn grow_exact(&mut self, increment: NonZeroUsize) {
135-
// If we got here with ZST, we requested total capacity > usize::MAX.
136-
assert!(self.item_layout.size() != 0, "ZST capacity overflow");
137-
138-
let new_capacity = self.capacity + increment.get();
135+
let new_capacity = self
136+
.capacity
137+
.checked_add(increment.get())
138+
.expect("capacity overflow");
139139
let new_layout =
140140
array_layout(&self.item_layout, new_capacity).expect("array layout should be valid");
141141
let new_data = if self.capacity == 0 {
@@ -621,7 +621,7 @@ mod tests {
621621
}
622622

623623
#[test]
624-
#[should_panic(expected = "ZST capacity overflow")]
624+
#[should_panic(expected = "capacity overflow")]
625625
fn blob_vec_zst_size_overflow() {
626626
// SAFETY: no drop is correct drop for `()`.
627627
let mut blob_vec = unsafe { BlobVec::new(Layout::new::<()>(), None, 0) };
@@ -644,6 +644,24 @@ mod tests {
644644
}
645645
}
646646

647+
#[test]
648+
#[should_panic(expected = "capacity overflow")]
649+
fn blob_vec_capacity_overflow() {
650+
// SAFETY: no drop is correct drop for `u32`.
651+
let mut blob_vec = unsafe { BlobVec::new(Layout::new::<u32>(), None, 0) };
652+
653+
assert_eq!(0, blob_vec.capacity(), "Self-check");
654+
655+
OwningPtr::make(17u32, |ptr| {
656+
// SAFETY: we push the value of correct type.
657+
unsafe {
658+
blob_vec.push(ptr);
659+
}
660+
});
661+
662+
blob_vec.reserve_exact(usize::MAX);
663+
}
664+
647665
#[test]
648666
fn aligned_zst() {
649667
// NOTE: This test is explicitly for uncovering potential UB with miri.

0 commit comments

Comments
 (0)