diff --git a/src/read/cfi.rs b/src/read/cfi.rs index 5d3e89ca0..137feb02e 100644 --- a/src/read/cfi.rs +++ b/src/read/cfi.rs @@ -1107,24 +1107,29 @@ impl Augmentation { "Augmentation::parse should only be called if we have an augmentation" ); - let first = augmentation_str.read_u8()?; - if first != b'z' { - return Err(Error::UnknownAugmentation); - } - let mut augmentation = Augmentation::default(); - let augmentation_length = input.read_uleb128().and_then(R::Offset::from_u64)?; - let rest = &mut input.split(augmentation_length)?; + let mut parsed_first = false; + let mut data = None; while !augmentation_str.is_empty() { let ch = augmentation_str.read_u8()?; match ch { + b'z' => { + if parsed_first { + return Err(Error::UnknownAugmentation); + } + + let augmentation_length = input.read_uleb128().and_then(R::Offset::from_u64)?; + data = Some(input.split(augmentation_length)?); + } b'L' => { + let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?; let encoding = parse_pointer_encoding(rest)?; augmentation.lsda = Some(encoding); } b'P' => { + let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?; let encoding = parse_pointer_encoding(rest)?; let parameters = PointerEncodingParameters { bases: &bases.eh_frame, @@ -1137,12 +1142,15 @@ impl Augmentation { augmentation.personality = Some((encoding, personality)); } b'R' => { + let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?; let encoding = parse_pointer_encoding(rest)?; augmentation.fde_address_encoding = Some(encoding); } b'S' => augmentation.is_signal_trampoline = true, _ => return Err(Error::UnknownAugmentation), } + + parsed_first = true; } Ok(augmentation) @@ -6158,6 +6166,23 @@ mod tests { ); } + #[test] + fn test_augmentation_parse_just_signal_trampoline() { + let aug_str = &mut EndianSlice::new(b"S", LittleEndian); + let bases = Default::default(); + let address_size = 8; + let section = EhFrame::new(&[], LittleEndian); + let input = &mut EndianSlice::new(&[], LittleEndian); + + let mut augmentation = Augmentation::default(); + augmentation.is_signal_trampoline = true; + + assert_eq!( + Augmentation::parse(aug_str, &bases, address_size, §ion, input), + Ok(augmentation) + ); + } + #[test] fn test_augmentation_parse_unknown_part_of_z_augmentation() { // The 'Z' character is not defined by the z-style augmentation.