Skip to content

Commit 8171437

Browse files
committed
fix(naive_time): enforce exact width when parsing %H%M%S
1 parent bab9790 commit 8171437

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

src/format/parse.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,18 @@ where
371371
} else if s.starts_with('+') {
372372
try_consume!(scan::number(&s[1..], 1, usize::MAX))
373373
} else {
374-
// if there is no explicit sign, we respect the original `width`
374+
// Signed value with no sign — variable width (legacy behavior)
375375
try_consume!(scan::number(s, 1, width))
376376
}
377377
} else {
378-
try_consume!(scan::number(s, 1, width))
378+
// Enforce exact width for unsigned values like %H, %M, %S
379+
if s.len() < width {
380+
return Err(TOO_SHORT);
381+
}
382+
let (val_str, rest) = s.split_at(width);
383+
let val = val_str.parse::<i64>().map_err(|_| INVALID)?;
384+
s = rest;
385+
val
379386
};
380387
set(parsed, v)?;
381388
}

src/naive/time/tests.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,26 @@ fn test_overflowing_offset() {
380380
assert_eq!(t.overflowing_sub_offset(positive_offset).0, t - positive_offset);
381381
}
382382

383+
#[test]
384+
fn test_parse_from_str_enforces_exact_width() {
385+
assert_eq!(
386+
NaiveTime::parse_from_str("010203", "%H%M%S"),
387+
Ok(NaiveTime::from_hms_opt(1, 2, 3).unwrap())
388+
);
389+
390+
// Too short — should fail
391+
assert!(NaiveTime::parse_from_str("01023", "%H%M%S").is_err());
392+
393+
// Too long — should fail
394+
assert!(NaiveTime::parse_from_str("0102033", "%H%M%S").is_err());
395+
396+
// Another valid time
397+
assert_eq!(
398+
NaiveTime::parse_from_str("235959", "%H%M%S"),
399+
Ok(NaiveTime::from_hms_opt(23, 59, 59).unwrap())
400+
);
401+
}
402+
383403
#[test]
384404
#[cfg(feature = "rkyv-validation")]
385405
fn test_rkyv_validation() {

0 commit comments

Comments
 (0)