{"id":"e55fe48c2bba5018","repo":"rust-lang/rust","slug":"size-mul-doesn-t-fit-in-u64","errorCode":null,"errorMessage":"Size::mul: {} * {} doesn't fit in u64","messagePattern":"Size::mul: (.+?) \\* (.+?) doesn't fit in u64","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_abi/src/lib.rs","lineNumber":1019,"sourceCode":"        }))\n    }\n}\n\nimpl Mul<Size> for u64 {\n    type Output = Size;\n    #[inline]\n    fn mul(self, size: Size) -> Size {\n        size * self\n    }\n}\n\nimpl Mul<u64> for Size {\n    type Output = Size;\n    #[inline]\n    fn mul(self, count: u64) -> Size {\n        match self.bytes().checked_mul(count) {\n            Some(bytes) => Size::from_bytes(bytes),\n            None => panic!(\"Size::mul: {} * {} doesn't fit in u64\", self.bytes(), count),\n        }\n    }\n}\n\nimpl AddAssign for Size {\n    #[inline]\n    fn add_assign(&mut self, other: Size) {\n        *self = *self + other;\n    }\n}\n\n#[cfg(feature = \"nightly\")]\nimpl Step for Size {\n    #[inline]\n    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {\n        u64::steps_between(&start.bytes(), &end.bytes())\n    }\n","sourceCodeStart":1001,"sourceCodeEnd":1037,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_abi/src/lib.rs#L1001-L1037","documentation":"Thrown by the `Mul<u64>` impl for `Size` (compiler/rustc_abi/src/lib.rs:1019) when `self.bytes() * count` overflows u64. This operator is the standard way to size an array from its element stride and element count. As with `Add`/`Sub`, the module note (lib.rs:982-983) says to avoid it during layout computation and use `checked_mul` instead.","triggerScenarios":"Writing `stride * count` or `count * stride` where `stride` is a `Size` and `count` is `u64`. Tripped when an array length times its element size exceeds 2^64 bytes — e.g. `[u8; usize::MAX]`-shaped layouts or `count` loaded from unsized metadata without bounds checking.","commonSituations":"Custom DSTs whose trailing slice length is attacker-controlled or read from foreign ABI metadata; codegen backends sizing stack arrays; or bugs where `count` was meant to be element count but got misinterpreted as a byte count.","solutions":["Use `stride.checked_mul(count, cx)` which validates against `obj_size_bound()` and returns `Option<Size>`; surface failure as `LayoutError::SizeOverflow`.","Bound `count` against `cx.data_layout().obj_size_bound() / stride.bytes()` before multiplying.","Confirm `count` is the element count, not a raw byte total or a pointer stride."],"exampleFix":"// before\nlet array_size = stride * element_count;\n\n// after\nlet array_size = stride\n    .checked_mul(element_count, cx)\n    .ok_or(LayoutError::SizeOverflow)?;","handlingStrategy":"validation","validationCode":"// Size::mul panics on overflow. Use checked_mul or the layout-bounded helper.\nfn safe_mul(size: rustc_abi::Size, count: u64) -> Option<rustc_abi::Size> {\n    size.bytes().checked_mul(count).map(rustc_abi::Size::from_bytes)\n}\n// Preferred when a HasDataLayout is available (also bounds vs obj_size_bound()):\n// size.checked_mul(count, &cx)","typeGuard":"// Guard the product, not the type.\nfn fits_mul(size: rustc_abi::Size, count: u64) -> bool {\n    size.bytes().checked_mul(count).is_some()\n}","tryCatchPattern":"// Not recoverable; propagate None from checked_mul as a LayoutError::SizeOverflow.","preventionTips":["For array/stride sizing always go through checked_mul(count, &cx) so the obj_size_bound() cap is enforced.","Reject element counts from untrusted input before multiplying by stride.","The library comment again says: avoid the panicking operator during layout computation."],"tags":["rustc-abi","size","overflow","panic","layout","array"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}