summaryrefslogtreecommitdiffstats
path: root/openpgp
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-12-19 19:53:00 +0100
committerJustus Winter <justus@sequoia-pgp.org>2019-12-20 18:04:56 +0100
commit3a80d2a1866b57b8c07f62ce095d951458e18430 (patch)
treec049b88d5715b1f451ee613326937f3c9b2d2370 /openpgp
parentffe6305f8be2bfb4106db177985c709493c7383d (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')
-rw-r--r--openpgp/src/lib.rs13
-rw-r--r--openpgp/src/packet/aed.rs9
-rw-r--r--openpgp/src/packet/compressed_data.rs9
-rw-r--r--openpgp/src/packet/container.rs58
-rw-r--r--openpgp/src/packet/mod.rs4
-rw-r--r--openpgp/src/packet/seip.rs9
-rw-r--r--openpgp/src/parse/parse.rs14
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