Skip to content

parse_duration accepts whitespace inside numeric literals and changes the parsed value #69

@meng-xu-cs

Description

@meng-xu-cs

Summary

parse_duration currently ignores whitespace inside the active numeric span, which means malformed inputs are silently reinterpreted as different durations instead of being rejected.

This affects both:

  • integer parts, e.g. "1 2h" is parsed as 12h
  • fractional parts, e.g. "1. 5s" is parsed as 1.5s

The parser already supports whitespace between a value and its unit (for example "20 min 17 nsec"), so this report is specifically about digits continuing after whitespace has already appeared inside a number.

Disclaimer: this does not necessarily means a bug and could be interpreted as a design feature. However, even so, it might be a good idea to have some explicit documentation to rule out the confusion.

Reproduction

use std::time::Duration;
use humantime::parse_duration;

fn main() {
    assert_eq!(parse_duration("1 2h"), Ok(Duration::from_secs(12 * 60 * 60)));
    assert_eq!(parse_duration("1 2 3s"), Ok(Duration::from_secs(123)));
    assert_eq!(parse_duration("1. 5s"), Ok(Duration::new(1, 500_000_000)));
}

Expected behavior

These inputs should return a parse error.

Once a numeric literal has started, whitespace may be tolerated before the unit, but it should not allow later digits to continue the same number.

So these should stay valid:

assert!(parse_duration("20 min 17 nsec").is_ok());
assert!(parse_duration("1.5 s").is_ok());

But these should fail:

assert!(parse_duration("1 2h").is_err());
assert!(parse_duration("1 2 3s").is_err());
assert!(parse_duration("1. 5s").is_err());

Actual behavior

Whitespace is treated as ignorable while the parser is still accumulating the current integer/fractional span, so later digits are merged into the same number:

  • "1 2h"12h
  • "1 2 3s"123s
  • "1. 5s"1.5s

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions