diff --git a/der/src/reader.rs b/der/src/reader.rs index c34713d6b..d5e1cd622 100644 --- a/der/src/reader.rs +++ b/der/src/reader.rs @@ -4,7 +4,6 @@ pub(crate) mod pem; pub(crate) mod slice; -#[cfg(feature = "pem")] mod position; use crate::{ diff --git a/der/src/reader/position.rs b/der/src/reader/position.rs index e35a8a04f..46388389d 100644 --- a/der/src/reader/position.rs +++ b/der/src/reader/position.rs @@ -21,21 +21,9 @@ impl Position { } } - /// Get the input length. - pub(super) fn input_len(&self) -> Length { - self.input_len - } - - /// Get the current position. - pub(super) fn current(&self) -> Length { - self.position - } - /// Advance the current position by the given amount. /// - /// # Returns - /// - /// The new current position. + /// Returns the new current position. pub(super) fn advance(&mut self, amount: Length) -> Result { let new_position = (self.position + amount)?; @@ -51,6 +39,22 @@ impl Position { Ok(new_position) } + /// Get the current position. + pub(super) fn current(&self) -> Length { + self.position + } + + /// Get the input length. + pub(super) fn input_len(&self) -> Length { + self.input_len + } + + /// Get the remaining length. + pub(super) fn remaining_len(&self) -> Length { + debug_assert!(self.position <= self.input_len()); + self.input_len.saturating_sub(self.position) + } + /// Split a nested position tracker of the given size. /// /// # Returns diff --git a/der/src/reader/slice.rs b/der/src/reader/slice.rs index a0ec9b6dd..e4462a42a 100644 --- a/der/src/reader/slice.rs +++ b/der/src/reader/slice.rs @@ -1,5 +1,6 @@ //! Slice reader. +use super::position::Position; use crate::{BytesRef, Decode, EncodingRules, Error, ErrorKind, Length, Reader}; /// [`Reader`] which consumes an input byte slice. @@ -15,7 +16,7 @@ pub struct SliceReader<'a> { failed: bool, /// Position within the decoded slice. - position: Length, + position: Position, } impl<'a> SliceReader<'a> { @@ -39,15 +40,15 @@ impl<'a> SliceReader<'a> { bytes: BytesRef::new(bytes)?, encoding_rules, failed: false, - position: Length::ZERO, + position: Position::new(bytes.len().try_into()?), }) } - /// Return an error with the given [`ErrorKind`], annotating it with - /// context about where the error occurred. + /// Return an error with the given [`ErrorKind`], annotating it with context about where the + /// error occurred. pub fn error(&mut self, kind: ErrorKind) -> Error { self.failed = true; - kind.at(self.position) + kind.at(self.position.current()) } /// Did the decoding operation fail due to an error? @@ -56,25 +57,17 @@ impl<'a> SliceReader<'a> { self.failed } - /// Obtain the remaining bytes in this slice reader from the current cursor - /// position. + /// Obtain the remaining bytes in this slice reader from the current cursor position. pub(crate) fn remaining(&self) -> Result<&'a [u8], Error> { if self.is_failed() { - Err(ErrorKind::Failed.at(self.position)) + Err(ErrorKind::Failed.at(self.position.current())) } else { self.bytes .as_slice() - .get(self.position.try_into()?..) + .get(self.position.current().try_into()?..) .ok_or_else(|| Error::incomplete(self.input_len())) } } - /// Creates new [`SliceReader`] without advancing current reader. - pub(crate) fn new_nested_reader(&mut self, len: Length) -> Result { - let prefix_len = (self.position + len)?; - let mut nested_reader = self.clone(); - nested_reader.bytes = self.bytes.prefix(prefix_len)?; - Ok(nested_reader) - } } impl<'a> Reader<'a> for SliceReader<'a> { @@ -89,29 +82,26 @@ impl<'a> Reader<'a> for SliceReader<'a> { } fn position(&self) -> Length { - self.position + self.position.current() } /// Read nested data of the given length. + #[inline] fn read_nested(&mut self, len: Length, f: F) -> Result where F: FnOnce(&mut Self) -> Result, E: From, { - let mut nested_reader = self.new_nested_reader(len)?; - let ret = f(&mut nested_reader); - self.position = nested_reader.position; - self.failed = nested_reader.failed; - - match ret { - Ok(value) => { - nested_reader.finish().inspect_err(|_e| { - self.failed = true; - })?; - Ok(value) - } - Err(err) => Err(err), - } + // Slice `self.bytes` as a secondary check we don't read past end-of-slice + let bytes = self.bytes; + let prefix_len = (self.position.current() + len)?; + self.bytes = self.bytes.prefix(prefix_len)?; + + let resumption = self.position.split_nested(len)?; + let ret = f(self); + self.bytes = bytes; + self.position.resume_nested(resumption); + ret } fn read_slice(&mut self, len: Length) -> Result<&'a [u8], Error> { @@ -121,11 +111,11 @@ impl<'a> Reader<'a> for SliceReader<'a> { match self.remaining()?.get(..len.try_into()?) { Some(result) => { - self.position = (self.position + len)?; + self.position.advance(len)?; Ok(result) } None => Err(self.error(ErrorKind::Incomplete { - expected_len: (self.position + len)?, + expected_len: (self.position.current() + len)?, actual_len: self.input_len(), })), } @@ -142,27 +132,23 @@ impl<'a> Reader<'a> for SliceReader<'a> { } fn error(&mut self, kind: ErrorKind) -> Error { - self.failed = true; - kind.at(self.position) + self.error(kind) } - fn finish(self) -> Result<(), Error> { + fn finish(mut self) -> Result<(), Error> { if self.is_failed() { - Err(ErrorKind::Failed.at(self.position)) + Err(ErrorKind::Failed.at(self.position.current())) } else if !self.is_finished() { - Err(ErrorKind::TrailingData { - decoded: self.position, - remaining: self.remaining_len(), - } - .at(self.position)) + let decoded = self.position.current(); + let remaining = self.remaining_len(); + Err(self.error(ErrorKind::TrailingData { decoded, remaining })) } else { Ok(()) } } fn remaining_len(&self) -> Length { - debug_assert!(self.position <= self.input_len()); - self.input_len().saturating_sub(self.position) + self.position.remaining_len() } }