Skip to content

Commit

Permalink
Do not panic on overlong input or output
Browse files Browse the repository at this point in the history
  • Loading branch information
yescallop committed Apr 11, 2024
1 parent 7848c1d commit e47071c
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 25 deletions.
5 changes: 5 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ pub(crate) enum ParseErrorKind {
///
/// The error index points to the first byte of the address.
InvalidIpv6Addr,
/// The input length is greater than [`u32::MAX`].
///
/// The error index equals `0`.
OverlongInput,
}

/// An error occurred when parsing URI references.
Expand Down Expand Up @@ -63,6 +67,7 @@ impl<I> std::error::Error for ParseError<I> {}
pub(crate) enum ResolveErrorKind {
NonAbsoluteBase,
NonHierarchicalBase,
OverlongOutput,
// PathUnderflow,
}

Expand Down
2 changes: 2 additions & 0 deletions src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl<I> Display for ParseError<I> {
ParseErrorKind::InvalidOctet => "invalid percent-encoded octet at index ",
ParseErrorKind::UnexpectedChar => "unexpected character at index ",
ParseErrorKind::InvalidIpv6Addr => "invalid IPv6 address at index ",
ParseErrorKind::OverlongInput => "overlong input at index ",
};
write!(f, "{}{}", msg, self.index)
}
Expand All @@ -58,6 +59,7 @@ impl Display for ResolveError {
ResolveErrorKind::NonHierarchicalBase => {
"resolving non-same-document relative reference against non-hierarchical base URI"
}
ResolveErrorKind::OverlongOutput => "overlong output",
};
f.write_str(msg)
}
Expand Down
14 changes: 4 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,12 @@ impl<T> Uri<T> {
/// # Errors
///
/// Returns `Err` if the string does not match
/// the [`URI-reference`] ABNF rule from RFC 3986.
/// the [`URI-reference`] ABNF rule from RFC 3986 or
/// if the input length is greater than [`u32::MAX`].
///
/// You may recover an input [`String`] by calling [`ParseError::into_input`].
///
/// [`URI-reference`]: https://datatracker.ietf.org/doc/html/rfc3986/#section-4.1
///
/// # Panics
///
/// Panics if the input length is greater than [`u32::MAX`].
pub fn parse<I>(input: I) -> Result<Self, I::Err>
where
I: ToUri<Val = T>,
Expand Down Expand Up @@ -334,11 +331,8 @@ impl<'i, 'o, T: BorrowOrShare<'i, 'o, str>> Uri<T> {
///
/// # Errors
///
/// Returns `Err` if any of the above two **must**s is violated.
///
/// # Panics
///
/// Panics if the output length would be greater than [`u32::MAX`].
/// Returns `Err` if any of the above two **must**s is violated or
/// if the output length would be greater than [`u32::MAX`].
///
/// # Examples
///
Expand Down
24 changes: 12 additions & 12 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,20 @@ use core::{

type Result<T> = core::result::Result<T, crate::error::ParseError>;

/// Returns immediately with an error.
macro_rules! err {
($index:expr, $kind:ident) => {
return Err(crate::error::ParseError {
index: $index as u32,
kind: crate::error::ParseErrorKind::$kind,
input: (),
})
};
}

pub(crate) fn parse(bytes: &[u8]) -> Result<Meta> {
if bytes.len() > u32::MAX as usize {
panic!("input length > u32::MAX");
err!(0, OverlongInput);
}

let mut parser = Parser {
Expand All @@ -23,17 +34,6 @@ pub(crate) fn parse(bytes: &[u8]) -> Result<Meta> {
Ok(parser.out)
}

/// Returns immediately with an error.
macro_rules! err {
($index:expr, $kind:ident) => {
return Err(crate::error::ParseError {
index: $index as u32,
kind: crate::error::ParseErrorKind::$kind,
input: (),
})
};
}

/// URI parser.
///
/// # Invariants
Expand Down
8 changes: 5 additions & 3 deletions src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,11 @@ pub(crate) fn resolve(
buf.push_str(fragment.as_str());
}

assert!(buf.len() <= u32::MAX as usize, "output length > u32::MAX");

Ok(Uri { val: buf, meta })
if buf.len() <= u32::MAX as usize {
Ok(Uri { val: buf, meta })
} else {
Err(ResolveError(ResolveErrorKind::OverlongOutput))
}
}

/// Removes dot segments from an absolute path.
Expand Down

0 comments on commit e47071c

Please sign in to comment.