diff --git a/src/uu/numfmt/src/numfmt.rs b/src/uu/numfmt/src/numfmt.rs index 78202dcbdc8..080e0200e22 100644 --- a/src/uu/numfmt/src/numfmt.rs +++ b/src/uu/numfmt/src/numfmt.rs @@ -33,6 +33,19 @@ pub mod options; mod numeric; mod units; +// Returns `true` if the input is in scientific notation +fn is_scientific(input: &[u8]) -> bool { + if let Some(pos) = input.iter().position(|&b| b == b'E' || b == b'e') { + if pos < input.len() - 1 { + if input[pos + 1].is_ascii_digit() { + return true; + } + } + } + + false +} + /// Format a single line and write it, handling `--invalid` error modes. /// /// Returns `true` if the line contained invalid input (only possible in @@ -49,19 +62,6 @@ fn format_and_write( None => input_line, }; - // Return false if the input is in scientific notation - if let Some(pos) = line.iter().position(|&b| b == b'E' || b == b'e') { - if pos < line.len() - 1 { - if line[pos + 1].is_ascii_digit() { - let err = format!( - "invalid suffix in input: '{}'", - String::from_utf8_lossy(line) - ); - return Err(Box::new(NumfmtError::FormattingError(err))); - } - } - } - // In non-abort modes we buffer the formatted output so that on error we // can emit the original line instead. let buffer_output = !matches!(options.invalid, InvalidModes::Abort); @@ -72,7 +72,16 @@ fn format_and_write( write_formatted_with_delimiter(dest, line, options, eol) } else { match std::str::from_utf8(line) { - Ok(s) => write_formatted_with_whitespace(dest, s, options, eol), + Ok(s) => { + if is_scientific(s.as_bytes()) { + Err(format!( + "invalid suffix in input: '{}'", + String::from_utf8_lossy(line) + )) + } else { + write_formatted_with_whitespace(dest, s, options, eol) + } + } Err(_) => Err(translate!( "numfmt-error-invalid-number", "input" => escape_line(line).quote() diff --git a/tests/by-util/test_numfmt.rs b/tests/by-util/test_numfmt.rs index 9fba2f25b4f..54c3fe77905 100644 --- a/tests/by-util/test_numfmt.rs +++ b/tests/by-util/test_numfmt.rs @@ -1513,3 +1513,14 @@ fn test_locale_c_uses_period() { .succeeds() .stdout_is("1.5K\n"); } + +// https://github.com/uutils/coreutils/issues/11935 +// the rejection path bypasses --invalid=warn/ignore/fail handling +#[test] +fn test_ignores_invalid_mode_issue11935() { + new_ucmd!() + .args(&["--invalid=warn", "100", "1e5", "200"]) + .succeeds() + .stderr_is("numfmt: invalid suffix in input: '1e5'\n") + .stdout_is("100\n1e5\n200\n"); +}