{"record":{"id":"62fb14bd15f00129","repo":"bevyengine/bevy","slug":"cannot-reserve-a-larger-alignedvec","errorCode":null,"errorMessage":"cannot reserve a larger AlignedVec","messagePattern":"cannot reserve a larger AlignedVec","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/bevy_platform/src/collections/aligned_vec.rs","lineNumber":436,"sourceCode":"        let remaining = self.cap.wrapping_sub(self.len);\n        if additional > remaining {\n            self.do_reserve(additional);\n        }\n    }\n\n    /// Extend capacity after `reserve` has found it's necessary.\n    ///\n    /// Actually performing the extension is in this separate function marked\n    /// `#[cold]` to hint to compiler that this branch is not often taken.\n    /// This keeps the path for common case where capacity is already sufficient\n    /// as fast as possible, and makes `reserve` more likely to be inlined.\n    /// This is the same trick that Rust's `Vec::reserve` uses.\n    #[cold]\n    fn do_reserve(&mut self, additional: usize) {\n        let new_cap = self\n            .len\n            .checked_add(additional)\n            .expect(\"cannot reserve a larger AlignedVec\");\n        // SAFETY: `do_reserve` is only called when capacity grows\n        unsafe { self.grow_capacity_to(new_cap) };\n    }\n\n    /// Grows total capacity of vector to `new_cap` or more.\n    ///\n    /// Capacity after this call will be `new_cap` rounded up to next power of\n    /// 2, unless that would exceed maximum capacity, in which case capacity\n    /// is capped at the maximum.\n    ///\n    /// This is same growth strategy used by `reserve`, `push` and\n    /// `extend_from_slice`.\n    ///\n    /// Usually the safe methods `reserve` or `reserve_exact` are a better\n    /// choice. This method only exists as a micro-optimization for very\n    /// performance-sensitive code where the calculation of capacity\n    /// required has already been performed, and you want to avoid doing it\n    /// again.","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_platform/src/collections/aligned_vec.rs#L418-L454","documentation":"`AlignedVec` is bevy_platform's alignment-aware vector (used for GPU-friendly storage in no_std contexts). `reserve`/`push`/`extend_from_slice` funnel growth through the `#[cold]` `do_reserve`, which computes `len + additional` with `checked_add`; if the sum overflows `usize`, the `.expect(\"cannot reserve a larger AlignedVec\")` at crates/bevy_platform/src/collections/aligned_vec.rs:436 panics.","triggerScenarios":"Calling `reserve(additional)` (directly or via `push`/`extend_from_slice` growth) where `additional > usize::MAX - len` — in practice almost always a size-computation bug upstream: a negative count cast with `as usize`, an underflowed subtraction, or untrusted asset data whose header declares a near-`u64::MAX` element count.","commonSituations":"Asset parsers reserving from file headers; index/length math that mixed signed and unsigned types; fuzzing or corrupted input files feeding absurd sizes into a builder that uses AlignedVec.","solutions":["Debug where `additional` comes from — the panic means `len + additional` exceeds usize::MAX, which needs a ~2^64 request on 64-bit targets","Validate sizes read from files/network before reserving (reject when total byte size exceeds `isize::MAX`)","Fix the arithmetic: use `usize`/`u64` with `checked_*` math instead of `as usize` casts from signed values"],"exampleFix":"// before: negative/trusting count cast to usize\nlet count = header.count as usize; // header.count: i32, could be negative -> huge usize\nvec.reserve(count);\n\n// after: validate before reserving\nlet count = usize::try_from(header.count).map_err(|_| InvalidHeader)?;\nif count > vec.max_capacity().saturating_sub(vec.len()) {\n    return Err(InvalidHeader);\n}\nvec.reserve(count);","handlingStrategy":"validation","validationCode":"fn safe_reserve(vec: &AlignedVec<T>, additional: usize) -> bool {\n    additional <= usize::MAX - vec.len()\n        && vec.len() + additional <= vec.max_capacity()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate counts read from files/network against isize::MAX byte budgets before reserving","Use checked arithmetic (usize::try_from, checked_add) instead of `as usize` casts for sizes","Fuzz asset parsers: capacity panics are almost always corrupt-input bugs, not real memory needs"],"tags":["bevy","aligned-vec","capacity-overflow","panic","collections"],"backgroundTag":"allocation-capacity-overflow","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}