From 8356687d47468c4ba1b922319edd458079d75eff Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Wed, 12 Jun 2024 15:45:14 +1000 Subject: [PATCH] read/cfi: add parse_encoded_value This directly parses an encoded value, instead of relying on parse_encoded_pointer to skip the pointer handling. This is preparation for changing parse_encoded_pointer to return a different address type. Also add more validation for the FDE count encoding, since it seems like the right thing to do, but this could be removed again if it is a problem. --- src/read/cfi.rs | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/read/cfi.rs b/src/read/cfi.rs index 5aa88468..bb9d0556 100644 --- a/src/read/cfi.rs +++ b/src/read/cfi.rs @@ -169,7 +169,10 @@ impl EhFrameHdr { if fde_count_enc == constants::DW_EH_PE_omit || table_enc == constants::DW_EH_PE_omit { fde_count = 0 } else { - fde_count = parse_encoded_pointer(fde_count_enc, ¶meters, &mut reader)?.direct()?; + if fde_count_enc != fde_count_enc.format() { + return Err(Error::UnsupportedPointerEncoding); + } + fde_count = parse_encoded_value(fde_count_enc, ¶meters, &mut reader)?; } Ok(ParsedEhFrameHdr { @@ -1716,15 +1719,10 @@ impl FrameDescriptionEntry { ) -> Result<(u64, u64)> { let encoding = cie.augmentation().and_then(|a| a.fde_address_encoding); if let Some(encoding) = encoding { - let initial_address = parse_encoded_pointer(encoding, parameters, input)?; - // Ignore indirection. - let initial_address = initial_address.pointer(); - - // Address ranges cannot be relative to anything, so just grab the - // data format bits from the encoding. - let address_range = parse_encoded_pointer(encoding.format(), parameters, input)?; - Ok((initial_address, address_range.pointer())) + let initial_address = parse_encoded_pointer(encoding, parameters, input)?.pointer(); + let address_range = parse_encoded_value(encoding, parameters, input)?; + Ok((initial_address, address_range)) } else { let initial_address = input.read_address(cie.address_size)?; let address_range = input.read_address(cie.address_size)?; @@ -3604,7 +3602,16 @@ fn parse_encoded_pointer( _ => unreachable!(), }; - let offset = match encoding.format() { + let offset = parse_encoded_value(encoding, parameters, input)?; + Ok(Pointer::new(encoding, base.wrapping_add(offset))) +} + +fn parse_encoded_value( + encoding: constants::DwEhPe, + parameters: &PointerEncodingParameters<'_, R>, + input: &mut R, +) -> Result { + match encoding.format() { // Unsigned variants. constants::DW_EH_PE_absptr => input.read_address(parameters.address_size), constants::DW_EH_PE_uleb128 => input.read_uleb128(), @@ -3623,9 +3630,7 @@ fn parse_encoded_pointer( // That was all of the valid encoding formats. _ => unreachable!(), - }?; - - Ok(Pointer::new(encoding, base.wrapping_add(offset))) + } } #[cfg(test)]