summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-02-14 14:41:32 +0100
committerJustus Winter <justus@sequoia-pgp.org>2023-05-12 10:29:41 +0200
commitb6388f0906315d2de7164bae36fb4408bf7c383a (patch)
treef1cd9b51ed1a45542e35505a563d829373e679f9
parentc82beb9b30ec77b6edc291516bb87b6cb3e20307 (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.rs14
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);