From 0e10422201f0d96f207bb46b8daec440aa4b0d1a Mon Sep 17 00:00:00 2001 From: Stefan Holderbach Date: Mon, 10 Feb 2025 00:20:22 +0100 Subject: [PATCH] Fix overly permissive parsing after whitespace (#59) * Fix parsing logic after first whitespace The way the parse was implemented accepted additional numeric characters or `.` after the first valid `f64` literal but ignored them. This permitted more strings that are invalid following a strict grammar for byte sizes and silently ignores the further symbols without error. ``` 1.0 ...KB 1.0 42.0 B ``` This change makes those illegal. `1 000 B` was also subject to the bad `skip_while` ignoring the following `000`. In this version of the fix whitespace is not accepted as a digit separator. So it will raise an error if the user doesn't explicitly strip the whitespace instead of reporting a wrong value. * Add tests for invalid chars after whitespace * Add test documenting that whitespace is not a valid digit separator More following the old choices of using `f64::from_str` --------- Co-authored-by: Rob Ede --- src/parse.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index a5cca5b..218fe8b 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -10,9 +10,7 @@ impl std::str::FromStr for ByteSize { let number = take_while(value, |c| c.is_ascii_digit() || c == '.'); match number.parse::() { Ok(v) => { - let suffix = skip_while(value, |c| { - c.is_whitespace() || c.is_ascii_digit() || c == '.' - }); + let suffix = skip_while(&value[number.len()..], char::is_whitespace); match suffix.parse::() { Ok(u) => Ok(Self((v * u) as u64)), Err(error) => Err(format!( @@ -220,6 +218,11 @@ mod tests { assert!(parse("").is_err()); assert!(parse("a124GB").is_err()); + assert!(parse("1.3 42.0 B").is_err()); + assert!(parse("1.3 ... B").is_err()); + // The original implementation did not account for the possibility that users may + // use whitespace to visually separate digits, thus treat it as an error + assert!(parse("1 000 B").is_err()); } #[test]