From 3430a256c3eb2c3c7928e51a36d11d1d0faae08f Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Fri, 10 Jun 2022 11:14:02 +0200 Subject: XXX openpgp: This is the gist of how to fix #727. - We add a buffered-reader-based function to trait Parse. Then, we can use it in combination with buffered_reader::Mut to peel off single objects (like MPIs) from an input stream. --- openpgp/src/parse.rs | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs index 7ee0ab13..82479d7c 100644 --- a/openpgp/src/parse.rs +++ b/openpgp/src/parse.rs @@ -271,6 +271,19 @@ pub(crate) const RECOVERY_THRESHOLD: usize = 32 * 1024; /// This is a uniform interface to parse packets, messages, keys, and /// related data structures. pub trait Parse<'a, T> { + /// Reads from the given buffered reader. + fn from_buffered_reader(_reader: R) -> Result + where + R: BufferedReader<()> + 'a, + { + unimplemented!("XXX: First, implement this for all of our types, \ + then express it here over Self::from_reader. \ + While the default implementation doesn't reap \ + the improvements, it is no worse than using \ + from_reader directly. In 2.x, make this function \ + the mandatory one instead of from_reader.") + } + /// Reads from the given reader. fn from_reader(reader: R) -> Result; @@ -3005,15 +3018,40 @@ impl MPI { } impl<'a> Parse<'a, MPI> for MPI { - // Reads an MPI from `reader`. + fn from_buffered_reader(reader: R) -> Result + where + R: BufferedReader<()> + 'a, + { + let mut parser = PacketHeaderParser::new_naked( + Adapter::with_cookie(reader, Cookie::default())); + let r = Self::parse("(none_len)", "(none)", &mut parser)?; + parser.commit()?; + Ok(r) + } + fn from_reader(reader: R) -> Result { - let bio = buffered_reader::Generic::with_cookie( - reader, None, Cookie::default()); - let mut parser = PacketHeaderParser::new_naked(bio); - Self::parse("(none_len)", "(none)", &mut parser) + Self::from_buffered_reader(buffered_reader::Generic::new(reader, None)) } } +#[test] +fn parse_mpis() -> Result<()> { + use buffered_reader::{Memory, Mut}; + use crate::serialize::Marshal; + let zero = MPI::zero(); + let one = MPI::new(&[1]); + let mut buf = Vec::new(); + zero.serialize(&mut buf)?; + one.serialize(&mut buf)?; + let mut reader = Memory::new(&buf); + let parsed = MPI::from_buffered_reader(Mut::new(&mut reader))?; + assert_eq!(parsed, zero); + let parsed = MPI::from_buffered_reader(Mut::new(&mut reader))?; + assert_eq!(parsed, one); + assert!(reader.eof()); + Ok(()) +} + impl PKESK { /// Parses the body of an PK-ESK packet. fn parse<'a, T: 'a + BufferedReader>(mut php: PacketHeaderParser) -> Result> { -- cgit v1.2.3