Integer Overflow & Numeric Bugs
In debug builds, overflow panics in +, -, *. In release, two's complement wrapping unless you use checked_*, saturating_*, or wrapping_* explicitly.
Recipe
let total = a.checked_add(b).ok_or(Error::Overflow)?;
let cents: i64 = amount.parse().context("amount")?;Working Example
// User-influenced math
fn price_total(unit_cents: u32, qty: u32) -> Result<u32, Error> {
unit_cents.checked_mul(qty).ok_or(Error::Overflow)
}
// Float money anti-pattern
// Use integer cents or rust_decimal for currencyDebug vs release:
cargo test # may panic on overflow in debug
cargo build --release # wraps silently on + - *Use overflow-checks profile or explicit checked ops in prod paths.
Deep Dive
usize indexing: validate length before allocate. Division by zero still panics in release. Float: NaN comparisons need is_nan.
Gotchas
- Assuming debug behavior in prod - silent wrap. Fix: checked math on user input.
- Cast truncates -
u64 as u32. Fix:try_from. - Float for money - rounding bugs. Fix: integer cents.
- Negative to unsigned cast - huge values. Fix: validate sign before cast.
- Duration overflow - use
checked_addon durations.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
saturating_add | caps scores | financial totals need error |
wrapping_add | hash/crypto | business logic |
BigInt crate | unbounded | hot path simple ints |
FAQs
force overflow panic release?
overflow-checks = true in profile or use checked ops.
clippy lint?
arithmetic_side_effects and cast lints.
serde large numbers?
String deserialize for u64 in JSON when >2^53.
polars dtypes?
Explicit Int64 for ids; watch cast in expressions.
random mod?
Use unbiased range crates; avoid % bias.
time millis?
i64 millis; check add with chrono checked APIs.
simd overflow?
Same rules; explicit wrapping intrinsics if intended.
test overflow?
#[should_panic] debug only; checked returns Err in prod code.
crypto?
Use fixed-width ops; no accidental wrap.
audit?
grep as and bare + on user integers in hot paths.
Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.