diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-12-19 19:53:00 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-12-20 18:04:56 +0100 |
commit | 3a80d2a1866b57b8c07f62ce095d951458e18430 (patch) | |
tree | c049b88d5715b1f451ee613326937f3c9b2d2370 /openpgp/src | |
parent | ffe6305f8be2bfb4106db177985c709493c7383d (diff) |
openpgp: Keep track whether a container has been streamed.
- If a container was streamed, we can no longer compare it to other
packets. Keep track of that, and use it in Container::PartialEq.
- See #93.
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/lib.rs | 13 | ||||
-rw-r--r-- | openpgp/src/packet/aed.rs | 9 | ||||
-rw-r--r-- | openpgp/src/packet/compressed_data.rs | 9 | ||||
-rw-r--r-- | openpgp/src/packet/container.rs | 58 | ||||
-rw-r--r-- | openpgp/src/packet/mod.rs | 4 | ||||
-rw-r--r-- | openpgp/src/packet/seip.rs | 9 | ||||
-rw-r--r-- | openpgp/src/parse/parse.rs | 14 |
7 files changed, 108 insertions, 8 deletions
diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs index f503f77f..3bca389f 100644 --- a/openpgp/src/lib.rs +++ b/openpgp/src/lib.rs @@ -285,8 +285,19 @@ pub enum Error { /// than a `CompressedData` packet. /// /// [Section 5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5 +/// +/// # A note on partial equality +/// +/// Container packets, like the [`CompressedData`] and the [`SEIP`] +/// packet, can be streamed. If a packet is streamed, we no longer +/// have access to the content, and therefore cannot compare it to +/// other packets. Consequently, a streamed packet is not considered +/// equal to any other packet. +/// +/// [`CompressedData`]: packet/struct.CompressedData.html +/// [`SEIP`]: packet/enum.SEIP.html #[derive(Debug)] -#[derive(PartialEq, Eq, Hash, Clone)] +#[derive(PartialEq, Hash, Clone)] pub enum Packet { /// Unknown packet. Unknown(packet::Unknown), diff --git a/openpgp/src/packet/aed.rs b/openpgp/src/packet/aed.rs index 1dfe579b..c5d69391 100644 --- a/openpgp/src/packet/aed.rs +++ b/openpgp/src/packet/aed.rs @@ -17,7 +17,14 @@ use crate::Result; /// of RFC 4880bis] for details. /// /// [Section 5.16 of RFC 4880bis]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-05#section-5.16 -#[derive(PartialEq, Eq, Hash, Clone, Debug)] +/// +/// # A note on partial equality +/// +/// Container packets, like this one, can be streamed. If a packet is +/// streamed, we no longer have access to the content, and therefore +/// cannot compare it to other packets. Consequently, a streamed +/// packet is not considered equal to any other packet. +#[derive(PartialEq, Hash, Clone, Debug)] pub struct AED1 { /// CTB packet header fields. pub(crate) common: packet::Common, diff --git a/openpgp/src/packet/compressed_data.rs b/openpgp/src/packet/compressed_data.rs index 2483a7c5..684b0358 100644 --- a/openpgp/src/packet/compressed_data.rs +++ b/openpgp/src/packet/compressed_data.rs @@ -15,7 +15,14 @@ use crate::types::CompressionAlgorithm; /// of a `CompressedData` packet. /// /// [Section 5.6 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.6 -#[derive(PartialEq, Eq, Hash, Clone)] +/// +/// # A note on partial equality +/// +/// Container packets, like this one, can be streamed. If a packet is +/// streamed, we no longer have access to the content, and therefore +/// cannot compare it to other packets. Consequently, a streamed +/// packet is not considered equal to any other packet. +#[derive(PartialEq, Hash, Clone)] pub struct CompressedData { /// CTB packet header fields. pub(crate) common: packet::Common, diff --git a/openpgp/src/packet/container.rs b/openpgp/src/packet/container.rs index e66206d9..2da4700f 100644 --- a/openpgp/src/packet/container.rs +++ b/openpgp/src/packet/container.rs @@ -16,7 +16,14 @@ use crate::{ /// /// This is used by OpenPGP container packets, like the compressed /// data packet, to store the containing packets. -#[derive(PartialEq, Eq, Hash, Clone)] +/// +/// # A note on partial equality +/// +/// Container packets, like this one, can be streamed. If a packet is +/// streamed, we no longer have access to the content, and therefore +/// cannot compare it to other packets. Consequently, a streamed +/// packet is not considered equal to any other packet. +#[derive(Hash, Clone)] pub(crate) struct Container { /// Used by container packets (such as the encryption and /// compression packets) to reference their immediate children. @@ -79,6 +86,24 @@ pub(crate) struct Container { /// this is not the packet's entire content; it is just the unread /// content. body: Vec<u8>, + + /// Remembers whether or not this packet has been streamed. + /// + /// If it has, then we lost (parts of) the content, and cannot + /// compare it to other packets. + was_streamed: bool, +} + +impl PartialEq for Container { + fn eq(&self, other: &Container) -> bool { + if self.was_streamed || other.was_streamed { + // If either was streamed, consider them not equal. + false + } else { + self.packets == other.packets + && self.body == other.body + } + } } impl Default for Container { @@ -86,6 +111,7 @@ impl Default for Container { Self { packets: Vec::with_capacity(0), body: Vec::with_capacity(0), + was_streamed: false, } } } @@ -95,6 +121,7 @@ impl From<Vec<Packet>> for Container { Self { packets, body: Vec::with_capacity(0), + was_streamed: false, } } } @@ -167,6 +194,19 @@ impl Container { std::mem::replace(&mut self.body, data) } + /// Returns whether or not this packet has been streamed. + /// + /// If it has, then we lost (parts of) the content, and cannot + /// compare it to other packets. + pub fn was_streamed(&self) -> bool { + self.was_streamed + } + + /// Sets whether or not this packet has been streamed. + pub(crate) fn set_streamed(&mut self, value: bool) { + self.was_streamed = value; + } + pub(crate) // For parse.rs fn body_mut(&mut self) -> &mut Vec<u8> { &mut self.body @@ -239,6 +279,14 @@ macro_rules! impl_container_forwards { self.container.set_body(data) } + /// Returns whether or not this packet has been streamed. + /// + /// If it has, then we lost (parts of) the content, and cannot + /// compare it to other packets. + pub fn was_streamed(&self) -> bool { + self.container.was_streamed() + } + /// Returns an iterator over the packet's immediate children. pub fn children<'a>(&'a self) -> impl Iterator<Item = &'a Packet> { self.container.children() @@ -293,4 +341,12 @@ impl Packet { pub(crate) fn body(&self) -> Option<&[u8]> { self.container_ref().map(|c| c.body()) } + + /// Returns whether or not this packet has been streamed. + /// + /// If it has, then we lost (parts of) the content, and cannot + /// compare it to other packets. + pub fn was_streamed(&self) -> bool { + self.container_ref().map(|c| c.was_streamed()).unwrap_or(false) + } } diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs index 86f028de..fc55a376 100644 --- a/openpgp/src/packet/mod.rs +++ b/openpgp/src/packet/mod.rs @@ -608,7 +608,7 @@ impl<P: key::KeyParts, R: key::KeyRole> DerefMut for Key<P, R> { /// 4880] for details. /// /// [Section 5.13 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.13 -#[derive(PartialEq, Eq, Hash, Clone, Debug)] +#[derive(PartialEq, Hash, Clone, Debug)] pub enum SEIP { /// SEIP packet version 1. V1(self::seip::SEIP1), @@ -655,7 +655,7 @@ impl DerefMut for SEIP { /// of RFC 4880bis] for details. /// /// [Section 5.16 of RFC 4880bis]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-05#section-5.16 -#[derive(PartialEq, Eq, Hash, Clone, Debug)] +#[derive(PartialEq, Hash, Clone, Debug)] pub enum AED { /// AED packet version 1. V1(self::aed::AED1), diff --git a/openpgp/src/packet/seip.rs b/openpgp/src/packet/seip.rs index 5a1872e7..a9ebada2 100644 --- a/openpgp/src/packet/seip.rs +++ b/openpgp/src/packet/seip.rs @@ -15,7 +15,14 @@ use crate::Packet; /// 4880] for details. /// /// [Section 5.13 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.13 -#[derive(PartialEq, Eq, Hash, Clone, Debug)] +/// +/// # A note on partial equality +/// +/// Container packets, like this one, can be streamed. If a packet is +/// streamed, we no longer have access to the content, and therefore +/// cannot compare it to other packets. Consequently, a streamed +/// packet is not considered equal to any other packet. +#[derive(PartialEq, Hash, Clone, Debug)] pub struct SEIP1 { /// CTB packet header fields. pub(crate) common: packet::Common, diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs index 3c46726b..3722f79b 100644 --- a/openpgp/src/parse/parse.rs +++ b/openpgp/src/parse/parse.rs @@ -3442,7 +3442,7 @@ impl <'a> PacketParser<'a> { } else { self.state = state_; self.finish()?; - // XXX self.content_was_read = false; + // XXX self.set_content_was_read(false); let (fake_eof_, reader_) = buffered_reader_stack_pop( reader_, recursion_depth - 1)?; fake_eof = fake_eof_; @@ -3600,7 +3600,12 @@ impl <'a> PacketParser<'a> { /// # return Ok(()); /// # } pub fn buffer_unread_content(&mut self) -> Result<&[u8]> { + // If the packet has not yet been streamed, then the following + // read operation should not be considered streaming. + let content_was_read = self.content_was_read; let mut rest = self.steal_eof()?; + self.set_content_was_read(content_was_read); + match &mut self.packet { Packet::Literal(p) => { if rest.len() > 0 { @@ -3721,10 +3726,17 @@ impl <'a> PacketParser<'a> { /// Sets the content_was_read flag if `cond` is true. fn mark_content_was_read(&mut self, cond: bool) { if cond { + self.packet.container_mut().map(|c| c.set_streamed(true)); self.content_was_read = true; } } + /// Sets the content_was_read flag to `value`. + fn set_content_was_read(&mut self, value: bool) { + self.packet.container_mut().map(|c| c.set_streamed(value)); + self.content_was_read = value; + } + /// Returns a reference to the current packet's header. pub fn header(&self) -> &Header { &self.header |