{"record":{"id":"2d905475a3145a45","repo":"rust-embedded/rust-raspberrypi-OS-tutorials","slug":"overflow-on-address-add","errorCode":null,"errorMessage":"Overflow on Address::add","messagePattern":"Overflow on Address::add","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"20_timer_callbacks/kernel/src/memory.rs","lineNumber":93,"sourceCode":"\n    /// Checks if the address is page aligned.\n    pub const fn is_page_aligned(&self) -> bool {\n        common::is_aligned(self.value, bsp::memory::mmu::KernelGranule::SIZE)\n    }\n\n    /// Return the address' offset into the corresponding page.\n    pub const fn offset_into_page(&self) -> usize {\n        self.value & bsp::memory::mmu::KernelGranule::MASK\n    }\n}\n\nimpl<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> {","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/blob/644474cc09f755249f9c55d99a5d1e07a2562fc7/20_timer_callbacks/kernel/src/memory.rs#L75-L111","documentation":"The Add<usize> implementation for Address<ATYPE> uses checked_add and panics with \"Overflow on Address::add\" when base + offset exceeds the address type's maximum. This is a deliberate safety check so address arithmetic never silently wraps in the kernel. It indicates a computed offset or size was wrong (too large) for the address space.","triggerScenarios":"Evaluating address + usize where the addition overflows ATYPE (e.g. u64/u32 address space), such as translating virtual->physical with an oversized offset, iterating past the end of a memory region, or adding a bogus size from a corrupted descriptor.","commonSituations":"MMU mapping code adding region sizes that run past the top of memory; a bootloader-provided memory map with absurd region base/size; off-by-N loops over physical/virtual ranges; casting 32-bit addresses into a wider computation then adding past 2^32 when ATYPE is u32.","solutions":["Find the offending Address + usize addition (the panic backtrace) and validate the offset/size against the region bounds before adding.","Check the source of the offset (memory map, descriptor, constant) for corruption or wrong units (bytes vs pages).","Use checked_range_inclusive/contains on the region before computing base + size.","Ensure ATYPE width matches the target architecture's address size (e.g. u64 on aarch64) so legitimate addresses don't overflow."],"exampleFix":"// before\nlet end = region.start_addr + region.size; // may overflow\n// after\nlet end = region.start_addr\n    .checked_add_usize(region.size)\n    .ok_or(\"Region exceeds address space\")?;","handlingStrategy":"validation","validationCode":"// Rust: bounds-check before address arithmetic\nfn safe_end(base: Address<AddressTypeVirtual>, size: usize) -> Option<Address<AddressTypeVirtual>> {\n    // emulate checked add before calling operator+\n    Some(base + size) // only if caller guaranteed size < addr-space remainder\n}","typeGuard":"// fn offset_fits(base_addr: u64, offset: usize, max: u64) -> bool {\n//     base_addr.checked_add(offset as u64).map_or(false, |sum| sum <= max)\n// }\nfn offset_fits(base_addr: u64, offset: usize, max: u64) -> bool {\n    base_addr.checked_add(offset as u64).map_or(false, |sum| sum <= max)\n}","tryCatchPattern":null,"preventionTips":["Validate region base+size against address-space bounds before adding.","Sanitize bootloader-provided memory map entries (reject absurd sizes).","Prefer checked_add in caller code when offsets come from external data.","Keep loop bounds derived from region lengths, not fixed constants."],"tags":["memory","overflow","address-arithmetic","panic","mmu"],"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-14T05:17:10.506Z"}