From d3e27bc35a40d8d87cb7a7a6a7add8f575756d28 Mon Sep 17 00:00:00 2001 From: Josh French Date: Tue, 7 Apr 2026 11:31:42 -0700 Subject: [PATCH] cksum: fix parsing error with tagged cheksum files When passed the '-c'/'--check' flag, and parsing a checksum file in the "tagged" format, cksum (symlinked to sha256sum, etc...) expects a line that looks like this: ShA256 (file.bin) = da39a3ee5e6b4b0d3255bfef95601890afd80709 If the hash algorithm at the beginning of the line (in the above case SHA256) is missing, then cksum panics because it is attempts to use the value of an array at index -1. This fix causes cksum to instead consider the line a syntax error and ignore it, just as GNU cksum does. I also added unit and integration tests to check for the above behaviour. --- .../src/lib/features/checksum/validate.rs | 9 +++++++++ tests/by-util/test_cksum.rs | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/uucore/src/lib/features/checksum/validate.rs b/src/uucore/src/lib/features/checksum/validate.rs index bb47ff6c920..dae9f26d027 100644 --- a/src/uucore/src/lib/features/checksum/validate.rs +++ b/src/uucore/src/lib/features/checksum/validate.rs @@ -281,6 +281,11 @@ impl LineFormat { // tagged format does not put a space before (filename) let par_idx = rest.iter().position(|&b| b == b'(')?; + // If the parenthesis is the first character (minus whitespace, which has already been stripped out), then, + // it's not a validly formatted line. + if par_idx < 1 { + return None; + } let sub_case = if rest[par_idx - 1] == b' ' { SubCase::Posix } else { @@ -1041,6 +1046,10 @@ mod tests { (b" MD5(weirdfilename6) = ) = fds65dsf46as5df4d6f54asds5d7f7g9", None), (b" MD5 (weirdfilename7)= )= fds65dsf46as5df4d6f54asds5d7f7g9", None), (b" MD5 (weirdfilename8) = )= fds65dsf46as5df4d6f54asds5d7f7g9", None), + // test for missing algorithm + (b"(filename) = fds65dsf46as5df4d6f54asds5d7f7g9", None), + (b"filename) = fds65dsf46as5df4d6f54asds5d7f7g9", None), + (b"filename = fds65dsf46as5df4d6f54asds5d7f7g9", None), ]; // cspell:enable diff --git a/tests/by-util/test_cksum.rs b/tests/by-util/test_cksum.rs index 16ed6d8b373..e2128b48a8b 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -627,6 +627,24 @@ fn test_check_sha2_tagged_missing_hint() { .stderr_contains("no properly formatted checksum lines found"); } +#[test] +fn test_check_tagged_missing_algo() { + // When checking tagged lines, if the algorithm is missing, print an "improperly + // formatted" message rather than panic. + + let (at, mut ucmd) = at_and_ucmd!(); + at.touch("a"); + + let invalid1 = "(a) = d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"; + let invalid2 = "a) = d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"; + let invalid3 = "(a = d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"; + + ucmd.arg("-c") + .pipe_in(format!("{invalid1}\n{invalid2}\n{invalid3}")) + .fails() + .stderr_contains("no properly formatted checksum lines found"); +} + #[rstest] #[case::md5("md5", "d41d8cd98f00b204e9800998ecf8427e")] #[case::sha1("sha1", "da39a3ee5e6b4b0d3255bfef95601890afd80709")]