diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-02-14 14:41:32 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2023-05-12 10:29:41 +0200 |
commit | b6388f0906315d2de7164bae36fb4408bf7c383a (patch) | |
tree | f1cd9b51ed1a45542e35505a563d829373e679f9 | |
parent | c82beb9b30ec77b6edc291516bb87b6cb3e20307 (diff) |
openpgp: Fix mapping of synthetic packets.
- If the packet parser encounters junk, it tries to recover by
finding the next plausible packet. Then, it returns the skipped
data in an synthetic packet. This packet has neither CTB nor
length.
- Previously, trying to access the data resulted in an out-of-bounds
subslicing.
- Fixes #985.
-rw-r--r-- | openpgp/src/parse/map.rs | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/openpgp/src/parse/map.rs b/openpgp/src/parse/map.rs index d5012e39..a1a1c2e1 100644 --- a/openpgp/src/parse/map.rs +++ b/openpgp/src/parse/map.rs @@ -117,10 +117,15 @@ assert_send_and_sync!(Field<'_>); impl<'a> Field<'a> { fn new(map: &'a Map, i: usize) -> Option<Field<'a>> { + // Synthetic packets have no CTB. + #[allow(clippy::len_zero)] + let has_ctb = map.header.len() > 0; + // Old-style CTB with indeterminate length emits no length // field. let has_length = map.header.len() > 1; - if i == 0 { + + if i == 0 && has_ctb { Some(Field { offset: 0, name: "CTB", @@ -133,8 +138,11 @@ impl<'a> Field<'a> { data: &map.header.as_slice()[1..] }) } else { - let offset_length = if has_length { 1 } else { 0 }; - map.entries.get(i - 1 - offset_length).map(|e| { + let offset = + if has_ctb { 1 } else { 0 } + + if has_length { 1 } else { 0 }; + + map.entries.get(i - offset).map(|e| { let len = map.data.len(); let start = cmp::min(len, e.offset); let end = cmp::min(len, e.offset + e.length); |