Skip to content

Commit adfc513

Browse files
authored
Stricter validation of RFC 6901 array indices (#80)
* introduces a strict check on index values as rust allows for leading '+' in parsing of uints. * [breaking] introduces a new variant of `ParseIndexError` to account for invalid characters.
1 parent 9a15d91 commit adfc513

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Adds method `into_buf` for `Box<Pointer>` and `impl From<PathBuf> for Box<Pointer>`.
1414
- Adds unsafe associated methods `Pointer::new_unchecked` and `PointerBuf::new_unchecked` for
1515
external zero-cost construction.
16+
- Adds new `ParseIndexError` variant to express the presence non-digit characters in the token.
1617
- Adds `Token::is_next` for checking if a token represents the `-` character.
1718

1819
### Changed
1920

2021
- Changed signature of `PathBuf::parse` to avoid requiring allocation.
2122
- Bumps minimum Rust version to 1.79.
2223

24+
### Fixed
25+
26+
- Make validation of array indices conform to RFC 6901 in the presence of non-digit characters.
27+
2328
## [0.6.2] 2024-09-30
2429

2530
### Added

src/assign.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,16 @@ mod tests {
767767
}),
768768
expected_data: json!([]),
769769
},
770+
Test {
771+
ptr: "/+23",
772+
data: json!([]),
773+
assign: json!("foo"),
774+
expected: Err(AssignError::FailedToParseIndex {
775+
offset: 0,
776+
source: ParseIndexError::InvalidCharacters("+".into()),
777+
}),
778+
expected_data: json!([]),
779+
},
770780
]);
771781
}
772782

src/index.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
//! ```
3737
3838
use crate::Token;
39-
use alloc::string::String;
39+
use alloc::{string::String, vec::Vec};
4040
use core::{fmt, num::ParseIntError, str::FromStr};
4141

4242
/// Represents an abstract index into an array.
@@ -166,7 +166,21 @@ impl FromStr for Index {
166166
} else if s.starts_with('0') && s != "0" {
167167
Err(ParseIndexError::LeadingZeros)
168168
} else {
169-
Ok(s.parse::<usize>().map(Index::Num)?)
169+
let idx = s.parse::<usize>().map(Index::Num)?;
170+
if s.chars().all(|c| c.is_ascii_digit()) {
171+
Ok(idx)
172+
} else {
173+
// this comes up with the `+` sign which is valid for
174+
// representing a `usize` but not allowed in RFC 6901 array
175+
// indices
176+
let mut invalid: Vec<_> = s.chars().filter(|c| !c.is_ascii_digit()).collect();
177+
// remove duplicate characters
178+
invalid.sort_unstable();
179+
invalid.dedup();
180+
Err(ParseIndexError::InvalidCharacters(
181+
invalid.into_iter().collect(),
182+
))
183+
}
170184
}
171185
}
172186
}
@@ -267,6 +281,8 @@ pub enum ParseIndexError {
267281
InvalidInteger(ParseIntError),
268282
/// The Token contains leading zeros.
269283
LeadingZeros,
284+
/// The Token contains non-digit characters.
285+
InvalidCharacters(String),
270286
}
271287

272288
impl From<ParseIntError> for ParseIndexError {
@@ -285,6 +301,11 @@ impl fmt::Display for ParseIndexError {
285301
f,
286302
"token contained leading zeros, which are disallowed by RFC 6901"
287303
),
304+
ParseIndexError::InvalidCharacters(chars) => write!(
305+
f,
306+
"token contains non-digit character(s) '{chars}', \
307+
which are disallowed by RFC 6901",
308+
),
288309
}
289310
}
290311
}
@@ -294,7 +315,7 @@ impl std::error::Error for ParseIndexError {
294315
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
295316
match self {
296317
ParseIndexError::InvalidInteger(source) => Some(source),
297-
ParseIndexError::LeadingZeros => None,
318+
ParseIndexError::LeadingZeros | ParseIndexError::InvalidCharacters(_) => None,
298319
}
299320
}
300321
}
@@ -413,6 +434,11 @@ mod tests {
413434
ParseIndexError::LeadingZeros.to_string(),
414435
"token contained leading zeros, which are disallowed by RFC 6901"
415436
);
437+
assert_eq!(
438+
ParseIndexError::InvalidCharacters("+@".into()).to_string(),
439+
"token contains non-digit character(s) '+@', \
440+
which are disallowed by RFC 6901"
441+
);
416442
}
417443

418444
#[test]

0 commit comments

Comments
 (0)