rust-lang/rust · critical
Size::mul: {} * {} doesn't fit in u64
Error message
Size::mul: {} * {} doesn't fit in u64 What it means
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.
Source
Thrown at compiler/rustc_abi/src/lib.rs:1019
}))
}
}
impl Mul<Size> for u64 {
type Output = Size;
#[inline]
fn mul(self, size: Size) -> Size {
size * self
}
}
impl Mul<u64> for Size {
type Output = Size;
#[inline]
fn mul(self, count: u64) -> Size {
match self.bytes().checked_mul(count) {
Some(bytes) => Size::from_bytes(bytes),
None => panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count),
}
}
}
impl AddAssign for Size {
#[inline]
fn add_assign(&mut self, other: Size) {
*self = *self + other;
}
}
#[cfg(feature = "nightly")]
impl Step for Size {
#[inline]
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
u64::steps_between(&start.bytes(), &end.bytes())
}
View on GitHub (pinned to 22057b88b0)
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.
Example fix
// before
let array_size = stride * element_count;
// after
let array_size = stride
.checked_mul(element_count, cx)
.ok_or(LayoutError::SizeOverflow)?; Defensive patterns
Strategy: validation
Validate before calling
// Size::mul panics on overflow. Use checked_mul or the layout-bounded helper.
fn safe_mul(size: rustc_abi::Size, count: u64) -> Option<rustc_abi::Size> {
size.bytes().checked_mul(count).map(rustc_abi::Size::from_bytes)
}
// Preferred when a HasDataLayout is available (also bounds vs obj_size_bound()):
// size.checked_mul(count, &cx) Type guard
// Guard the product, not the type.
fn fits_mul(size: rustc_abi::Size, count: u64) -> bool {
size.bytes().checked_mul(count).is_some()
} Try / catch
// Not recoverable; propagate None from checked_mul as a LayoutError::SizeOverflow.
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Size::bits: {bytes} bytes in bits doesn't fit in u64
- Size::add: {} + {} doesn't fit in u64
- Size::sub: {} - {} would result in negative size
- cannot change the valid range of a union
- Layout of fields should be Arbitrary for variants
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/e55fe48c2bba5018.json.
Report an issue: GitHub.