From 925719258fc2f2f0e75de22aa40dae96f854222b Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Thu, 4 Jul 2024 11:59:36 +1000 Subject: [PATCH] read/cfi: check for overflow when evaluating DW_CFA_advance_loc (#730) Addresses for CFI rows should only increase. This is equivalent to the existing check for DW_CFA_set_loc. --- src/read/cfi.rs | 16 ++++++++++++---- src/read/mod.rs | 6 ++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/read/cfi.rs b/src/read/cfi.rs index 72b19cc2..efaed873 100644 --- a/src/read/cfi.rs +++ b/src/read/cfi.rs @@ -2361,7 +2361,13 @@ where } AdvanceLoc { delta } => { let delta = Wrapping(u64::from(delta)) * self.code_alignment_factor; - self.next_start_address = (Wrapping(self.ctx.start_address()) + delta).0; + let address = self + .ctx + .start_address() + .checked_add(delta.0) + .ok_or(Error::AddressOverflow)?; + + self.next_start_address = address; self.ctx.row_mut().end_address = self.next_start_address; return Ok(true); } @@ -5481,9 +5487,11 @@ mod tests { let cie = make_test_cie(); let mut ctx = UnwindContext::new(); ctx.row_mut().start_address = u64::MAX; - let mut expected = ctx.clone(); - expected.row_mut().end_address = 42 * cie.code_alignment_factor - 1; - let instructions = [(Ok(true), CallFrameInstruction::AdvanceLoc { delta: 42 })]; + let expected = ctx.clone(); + let instructions = [( + Err(Error::AddressOverflow), + CallFrameInstruction::AdvanceLoc { delta: 42 }, + )]; assert_eval(ctx, expected, cie, None, instructions); } diff --git a/src/read/mod.rs b/src/read/mod.rs index e855aa74..5731e7fe 100644 --- a/src/read/mod.rs +++ b/src/read/mod.rs @@ -386,6 +386,11 @@ pub enum Error { UnknownCallFrameInstruction(constants::DwCfa), /// The end of an address range was before the beginning. InvalidAddressRange, + /// An address calculation overflowed. + /// + /// This is returned in cases where the address is expected to be + /// larger than a previous address, but the calculation overflowed. + AddressOverflow, /// Encountered a call frame instruction in a context in which it is not /// valid. CfiInstructionInInvalidContext, @@ -543,6 +548,7 @@ impl Error { Error::InvalidAddressRange => { "The end of an address range must not be before the beginning." } + Error::AddressOverflow => "An address calculation overflowed.", Error::CfiInstructionInInvalidContext => { "Encountered a call frame instruction in a context in which it is not valid." }