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

  1. Use `stride.checked_mul(count, cx)` which validates against `obj_size_bound()` and returns `Option<Size>`; surface failure as `LayoutError::SizeOverflow`.
  2. Bound `count` against `cx.data_layout().obj_size_bound() / stride.bytes()` before multiplying.
  3. 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

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


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/e55fe48c2bba5018.json. Report an issue: GitHub.