Skip to content

Commit 0315477

Browse files
committed
fmt: fix panic bug in strptime when using %C
The code previously assumed that `%C` could never parse more than 2 digits. I believe this restriction was relaxed at some point, but the assumption was never revisited in this part of the code. This fixes the panic by forcefully restricting the absolute value of the parsed century to be in the range `0..=99`. Fixes #426
1 parent 5dcabd7 commit 0315477

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ is a fallback for `TimeZone::system()` (instead of the `jiff 0.1` behavior of
1818
using `TimeZone::UTC`).
1919
* [#423](https://github.com/BurntSushi/jiff/issues/423):
2020
Fix a panicking bug when reading malformed TZif data.
21+
* [#426](https://github.com/BurntSushi/jiff/issues/426):
22+
Fix a panicking bug when parsing century (`%C`) via `strptime`.
2123

2224

2325
0.2.15 (2025-06-13)

src/fmt/strtime/parse.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,12 @@ impl<'f, 'i, 't> Parser<'f, 'i, 't> {
861861
.context("failed to parse century")?;
862862
self.inp = inp;
863863

864+
if !(0 <= century && century <= 99) {
865+
return Err(err!(
866+
"century `{century}` is too big, must be in range 0-99",
867+
));
868+
}
869+
864870
// OK because sign=={1,-1} and century can't be bigger than 2 digits
865871
// so overflow isn't possible.
866872
let century = sign.checked_mul(century).unwrap();
@@ -2187,4 +2193,21 @@ mod tests {
21872193
@r#"strptime expects to consume the entire input, but "15" remains unparsed"#,
21882194
);
21892195
}
2196+
2197+
/// Regression test for checked arithmetic panicking.
2198+
///
2199+
/// Ref https://github.com/BurntSushi/jiff/issues/426
2200+
#[test]
2201+
fn err_parse_large_century() {
2202+
let p = |fmt: &str, input: &str| {
2203+
BrokenDownTime::parse_mono(fmt.as_bytes(), input.as_bytes())
2204+
.unwrap_err()
2205+
.to_string()
2206+
};
2207+
2208+
insta::assert_snapshot!(
2209+
p("%^50C%", "2000000000000000000#0077)()"),
2210+
@"strptime parsing failed: %C failed: century `2000000000000000000` is too big, must be in range 0-99",
2211+
);
2212+
}
21902213
}

0 commit comments

Comments
 (0)