Skip to content

Commit bbb0663

Browse files
authored
const-oid: handle repeated dot characters in input (#1595)
Adds an `Error::RepeatedDot` case and handles it within the parser
1 parent c872bb3 commit bbb0663

File tree

3 files changed

+43
-20
lines changed

3 files changed

+43
-20
lines changed

const-oid/src/error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ pub enum Error {
3737
/// OID length is invalid (too short or too long).
3838
Length,
3939

40+
/// Repeated `..` characters in input data.
41+
RepeatedDot,
42+
4043
/// Trailing `.` character at end of input.
4144
TrailingDot,
4245
}
@@ -53,6 +56,7 @@ impl Error {
5356
Error::DigitExpected { .. } => panic!("OID expected to start with digit"),
5457
Error::Empty => panic!("OID value is empty"),
5558
Error::Length => panic!("OID length invalid"),
59+
Error::RepeatedDot => panic!("repeated consecutive '..' characters in OID"),
5660
Error::TrailingDot => panic!("OID ends with invalid trailing '.'"),
5761
}
5862
}
@@ -69,6 +73,7 @@ impl fmt::Display for Error {
6973
}
7074
Error::Empty => f.write_str("OID value is empty"),
7175
Error::Length => f.write_str("OID length invalid"),
76+
Error::RepeatedDot => f.write_str("repeated consecutive '..' characters in OID"),
7277
Error::TrailingDot => f.write_str("OID ends with invalid trailing '.'"),
7378
}
7479
}

const-oid/src/parser.rs

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{encoder::Encoder, Arc, Error, ObjectIdentifier, Result};
88
#[derive(Debug)]
99
pub(crate) struct Parser {
1010
/// Current arc in progress
11-
current_arc: Arc,
11+
current_arc: Option<Arc>,
1212

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

2626
match bytes[0] {
2727
b'0'..=b'9' => Self {
28-
current_arc: 0,
28+
current_arc: None,
2929
encoder: Encoder::new(),
3030
}
3131
.parse_bytes(bytes),
@@ -42,37 +42,50 @@ impl Parser {
4242
const fn parse_bytes(mut self, bytes: &[u8]) -> Result<Self> {
4343
match bytes {
4444
// TODO(tarcieri): use `?` when stable in `const fn`
45-
[] => match self.encoder.arc(self.current_arc) {
46-
Ok(encoder) => {
47-
self.encoder = encoder;
48-
Ok(self)
49-
}
50-
Err(err) => Err(err),
45+
[] => match self.current_arc {
46+
Some(arc) => match self.encoder.arc(arc) {
47+
Ok(encoder) => {
48+
self.encoder = encoder;
49+
Ok(self)
50+
}
51+
Err(err) => Err(err),
52+
},
53+
None => Err(Error::TrailingDot),
5154
},
5255
[byte @ b'0'..=b'9', remaining @ ..] => {
5356
let digit = byte.saturating_sub(b'0');
54-
self.current_arc = match self.current_arc.checked_mul(10) {
57+
let arc = match self.current_arc {
58+
Some(arc) => arc,
59+
None => 0,
60+
};
61+
62+
self.current_arc = match arc.checked_mul(10) {
5563
Some(arc) => match arc.checked_add(digit as Arc) {
56-
Some(arc) => arc,
5764
None => return Err(Error::ArcTooBig),
65+
arc => arc,
5866
},
5967
None => return Err(Error::ArcTooBig),
6068
};
6169
self.parse_bytes(remaining)
6270
}
6371
[b'.', remaining @ ..] => {
64-
if remaining.is_empty() {
65-
return Err(Error::TrailingDot);
66-
}
72+
match self.current_arc {
73+
Some(arc) => {
74+
if remaining.is_empty() {
75+
return Err(Error::TrailingDot);
76+
}
6777

68-
// TODO(tarcieri): use `?` when stable in `const fn`
69-
match self.encoder.arc(self.current_arc) {
70-
Ok(encoder) => {
71-
self.encoder = encoder;
72-
self.current_arc = 0;
73-
self.parse_bytes(remaining)
78+
// TODO(tarcieri): use `?` when stable in `const fn`
79+
match self.encoder.arc(arc) {
80+
Ok(encoder) => {
81+
self.encoder = encoder;
82+
self.current_arc = None;
83+
self.parse_bytes(remaining)
84+
}
85+
Err(err) => Err(err),
86+
}
7487
}
75-
Err(err) => Err(err),
88+
None => Err(Error::RepeatedDot),
7689
}
7790
}
7891
[byte, ..] => Err(Error::DigitExpected { actual: *byte }),

const-oid/tests/oid.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,11 @@ fn parse_invalid_second_arc() {
241241
);
242242
}
243243

244+
#[test]
245+
fn parse_invalid_repeat_dots() {
246+
assert_eq!(ObjectIdentifier::new("1.2..3.4"), Err(Error::RepeatedDot))
247+
}
248+
244249
#[test]
245250
fn parent() {
246251
let child = oid("1.2.3.4");

0 commit comments

Comments
 (0)