{"record":{"id":"439bc35af3c67200","repo":"rust-embedded/rust-raspberrypi-OS-tutorials","slug":"overflow-on-address-sub","errorCode":null,"errorMessage":"Overflow on Address::sub","messagePattern":"Overflow on Address::sub","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"20_timer_callbacks/kernel/src/memory.rs","lineNumber":105,"sourceCode":"impl<ATYPE: AddressType> Add<usize> for Address<ATYPE> {\n    type Output = Self;\n\n    #[inline(always)]\n    fn add(self, rhs: usize) -> Self::Output {\n        match self.value.checked_add(rhs) {\n            None => panic!(\"Overflow on Address::add\"),\n            Some(x) => Self::new(x),\n        }\n    }\n}\n\nimpl<ATYPE: AddressType> Sub<usize> for Address<ATYPE> {\n    type Output = Self;\n\n    #[inline(always)]\n    fn sub(self, rhs: usize) -> Self::Output {\n        match self.value.checked_sub(rhs) {\n            None => panic!(\"Overflow on Address::sub\"),\n            Some(x) => Self::new(x),\n        }\n    }\n}\n\nimpl<ATYPE: AddressType> Sub<Address<ATYPE>> for Address<ATYPE> {\n    type Output = Self;\n\n    #[inline(always)]\n    fn sub(self, rhs: Address<ATYPE>) -> Self::Output {\n        match self.value.checked_sub(rhs.value) {\n            None => panic!(\"Overflow on Address::sub\"),\n            Some(x) => Self::new(x),\n        }\n    }\n}\n\nimpl Address<Virtual> {","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/blob/644474cc09f755249f9c55d99a5d1e07a2562fc7/20_timer_callbacks/kernel/src/memory.rs#L87-L123","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Audit the subtraction site and clamp/branch: only subtract when `address_value >= offset`, otherwise return None/stop the loop.","Compute from the correct base — subtract from the region end address, not the start.","Check for usize underflow from a negative value: verify the offset is not produced by casting a negative isize.","Replace the expression with checked arithmetic yourself (`checked_sub`) so you can handle the underflow case gracefully.","Add an assertion/log of the address and offset before the subtraction to identify the bad input."],"exampleFix":"// before\nlet base = region_start - size;\n// after\nlet base = region_start.checked_sub(size)\n    .ok_or(\"region start below heap base\")?;","handlingStrategy":"validation","validationCode":"fn safe_sub_usize(addr_value: usize, rhs: usize) -> Option<usize> {\n    addr_value.checked_sub(rhs)\n}","typeGuard":"fn can_sub(addr_value: usize, rhs: usize) -> bool {\n    addr_value >= rhs\n}","tryCatchPattern":"// Rust panics are not catchable here (no_std kernel); validate before:\nmatch addr.value.checked_sub(rhs) {\n    Some(x) => Address::new(x),\n    None => { /* handle underflow: stop loop / return error */ }\n}","preventionTips":["Always bound downward loops with an inclusive condition (e.g. `while addr > base`).","Never cast negative numbers to usize before subtracting.","Compute sizes from end - start, not offsets from start.","Prefer checked_sub at call sites when underflow is plausible."],"tags":["rust","kernel","overflow","memory"],"backgroundTag":"value-out-of-range","analyzedSha":"644474cc09f755249f9c55d99a5d1e07a2562fc7","analyzedAt":"2026-09-06T09:25:56.584Z","contentChangedAt":"2026-09-06T09:25:56.584Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}