From 0366d3c657ef02ff7c82dcd25926e0485db38ed2 Mon Sep 17 00:00:00 2001 From: Josh French Date: Mon, 20 Apr 2026 14:51:01 -0700 Subject: [PATCH] cksum: fix parsing error with tagged cheksum files (#11704) * 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. --------- Co-authored-by: Sylvestre Ledru --- .../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 bb47ff6c9..bd2993e82 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 == 0 { + 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 7e6615632..7998ae13d 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")]