rust-embedded/rust-raspberrypi-OS-tutorials · error

Overflow on Address::sub

Error message

Overflow on Address::sub

What it means

This panic is thrown by the Sub<usize> implementation for Address<ATYPE> when the checked subtraction of a usize offset from the address's underlying value underflows (result would be negative). The kernel wraps addresses in a typed Address struct and refuses to silently wrap on arithmetic overflow, so any pointer arithmetic that goes below zero panics instead. It exists to catch pointer-bug errors early in kernel code rather than corrupting memory.

Source

Thrown at 20_timer_callbacks/kernel/src/memory.rs:105

impl<ATYPE: AddressType> Add<usize> for Address<ATYPE> {
    type Output = Self;

    #[inline(always)]
    fn add(self, rhs: usize) -> Self::Output {
        match self.value.checked_add(rhs) {
            None => panic!("Overflow on Address::add"),
            Some(x) => Self::new(x),
        }
    }
}

impl<ATYPE: AddressType> Sub<usize> for Address<ATYPE> {
    type Output = Self;

    #[inline(always)]
    fn sub(self, rhs: usize) -> Self::Output {
        match self.value.checked_sub(rhs) {
            None => panic!("Overflow on Address::sub"),
            Some(x) => Self::new(x),
        }
    }
}

impl<ATYPE: AddressType> Sub<Address<ATYPE>> for Address<ATYPE> {
    type Output = Self;

    #[inline(always)]
    fn sub(self, rhs: Address<ATYPE>) -> Self::Output {
        match self.value.checked_sub(rhs.value) {
            None => panic!("Overflow on Address::sub"),
            Some(x) => Self::new(x),
        }
    }
}

impl Address<Virtual> {

View on GitHub (pinned to 644474cc09)

Solutions

  1. Audit the subtraction site and clamp/branch: only subtract when `address_value >= offset`, otherwise return None/stop the loop.
  2. Compute from the correct base — subtract from the region end address, not the start.
  3. Check for usize underflow from a negative value: verify the offset is not produced by casting a negative isize.
  4. Replace the expression with checked arithmetic yourself (`checked_sub`) so you can handle the underflow case gracefully.
  5. Add an assertion/log of the address and offset before the subtraction to identify the bad input.

Example fix

// before
let base = region_start - size;
// after
let base = region_start.checked_sub(size)
    .ok_or("region start below heap base")?;
Defensive patterns

Strategy: validation

Validate before calling

fn safe_sub_usize(addr_value: usize, rhs: usize) -> Option<usize> {
    addr_value.checked_sub(rhs)
}

Type guard

fn can_sub(addr_value: usize, rhs: usize) -> bool {
    addr_value >= rhs
}

Try / catch

// Rust panics are not catchable here (no_std kernel); validate before:
match addr.value.checked_sub(rhs) {
    Some(x) => Address::new(x),
    None => { /* handle underflow: stop loop / return error */ }
}

Prevention

When it happens

Trigger: Calling `address - n` (or `*ptr.offset(-n)` style arithmetic via `-`) where n is larger than the address value, e.g. subtracting a size from the start of a virtual region, iterating downward past the base address, or passing a wrong/negative-derived offset.

Common situations: Downward loops over a memory region that run one iteration past the region start; subtracting a region size from the region start instead of the end; sign confusion where a usize cast of a negative number becomes huge; off-by-one in bounds computations for stack or heap layout.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of rust-embedded/rust-raspberrypi-OS-tutorials@644474cc09 (2026-09-06). Data as JSON: /api/errors/439bc35af3c67200. Report an issue: GitHub.