Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

const-oid: handle repeated dot characters in input #1595

Merged
merged 1 commit into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions const-oid/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ pub enum Error {
/// OID length is invalid (too short or too long).
Length,

/// Repeated `..` characters in input data.
RepeatedDot,

/// Trailing `.` character at end of input.
TrailingDot,
}
Expand All @@ -53,6 +56,7 @@ impl Error {
Error::DigitExpected { .. } => panic!("OID expected to start with digit"),
Error::Empty => panic!("OID value is empty"),
Error::Length => panic!("OID length invalid"),
Error::RepeatedDot => panic!("repeated consecutive '..' characters in OID"),
Error::TrailingDot => panic!("OID ends with invalid trailing '.'"),
}
}
Expand All @@ -69,6 +73,7 @@ impl fmt::Display for Error {
}
Error::Empty => f.write_str("OID value is empty"),
Error::Length => f.write_str("OID length invalid"),
Error::RepeatedDot => f.write_str("repeated consecutive '..' characters in OID"),
Error::TrailingDot => f.write_str("OID ends with invalid trailing '.'"),
}
}
Expand Down
53 changes: 33 additions & 20 deletions const-oid/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{encoder::Encoder, Arc, Error, ObjectIdentifier, Result};
#[derive(Debug)]
pub(crate) struct Parser {
/// Current arc in progress
current_arc: Arc,
current_arc: Option<Arc>,

/// BER/DER encoder
encoder: Encoder<{ ObjectIdentifier::MAX_SIZE }>,
Expand All @@ -25,7 +25,7 @@ impl Parser {

match bytes[0] {
b'0'..=b'9' => Self {
current_arc: 0,
current_arc: None,
encoder: Encoder::new(),
}
.parse_bytes(bytes),
Expand All @@ -42,37 +42,50 @@ impl Parser {
const fn parse_bytes(mut self, bytes: &[u8]) -> Result<Self> {
match bytes {
// TODO(tarcieri): use `?` when stable in `const fn`
[] => match self.encoder.arc(self.current_arc) {
Ok(encoder) => {
self.encoder = encoder;
Ok(self)
}
Err(err) => Err(err),
[] => match self.current_arc {
Some(arc) => match self.encoder.arc(arc) {
Ok(encoder) => {
self.encoder = encoder;
Ok(self)
}
Err(err) => Err(err),
},
None => Err(Error::TrailingDot),
},
[byte @ b'0'..=b'9', remaining @ ..] => {
let digit = byte.saturating_sub(b'0');
self.current_arc = match self.current_arc.checked_mul(10) {
let arc = match self.current_arc {
Some(arc) => arc,
None => 0,
};

self.current_arc = match arc.checked_mul(10) {
Some(arc) => match arc.checked_add(digit as Arc) {
Some(arc) => arc,
None => return Err(Error::ArcTooBig),
arc => arc,
},
None => return Err(Error::ArcTooBig),
};
self.parse_bytes(remaining)
}
[b'.', remaining @ ..] => {
if remaining.is_empty() {
return Err(Error::TrailingDot);
}
match self.current_arc {
Some(arc) => {
if remaining.is_empty() {
return Err(Error::TrailingDot);
}

// TODO(tarcieri): use `?` when stable in `const fn`
match self.encoder.arc(self.current_arc) {
Ok(encoder) => {
self.encoder = encoder;
self.current_arc = 0;
self.parse_bytes(remaining)
// TODO(tarcieri): use `?` when stable in `const fn`
match self.encoder.arc(arc) {
Ok(encoder) => {
self.encoder = encoder;
self.current_arc = None;
self.parse_bytes(remaining)
}
Err(err) => Err(err),
}
}
Err(err) => Err(err),
None => Err(Error::RepeatedDot),
}
}
[byte, ..] => Err(Error::DigitExpected { actual: *byte }),
Expand Down
5 changes: 5 additions & 0 deletions const-oid/tests/oid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@ fn parse_invalid_second_arc() {
);
}

#[test]
fn parse_invalid_repeat_dots() {
assert_eq!(ObjectIdentifier::new("1.2..3.4"), Err(Error::RepeatedDot))
}

#[test]
fn parent() {
let child = oid("1.2.3.4");
Expand Down
Loading