diff --git a/src/uucore/src/lib/features/checksum.rs b/src/uucore/src/lib/features/checksum.rs index 30eccc254..e59054561 100644 --- a/src/uucore/src/lib/features/checksum.rs +++ b/src/uucore/src/lib/features/checksum.rs @@ -837,25 +837,41 @@ fn identify_algo_name_and_length( last_algo: &mut Option, ) -> Result<(String, Option), LineCheckError> { let algo_from_line = line_info.algo_name.clone().unwrap_or_default(); - let algorithm = algo_from_line.to_lowercase(); + let line_algo = algo_from_line.to_lowercase(); *last_algo = Some(algo_from_line); - // check if we are called with XXXsum (example: md5sum) but we detected a different algo parsing the file - // (for example SHA1 (f) = d...) + // check if we are called with XXXsum (example: md5sum) but we detected a + // different algo parsing the file (for example SHA1 (f) = d...) + // // Also handle the case cksum -s sm3 but the file contains other formats - if algo_name_input.is_some() && algo_name_input != Some(&algorithm) { - return Err(LineCheckError::ImproperlyFormatted); + if let Some(algo_name_input) = algo_name_input { + match (algo_name_input, line_algo.as_str()) { + (l, r) if l == r => (), + // Edge case for SHA2, which matches SHA(224|256|384|512) + ( + ALGORITHM_OPTIONS_SHA2, + ALGORITHM_OPTIONS_SHA224 + | ALGORITHM_OPTIONS_SHA256 + | ALGORITHM_OPTIONS_SHA384 + | ALGORITHM_OPTIONS_SHA512, + ) => (), + _ => return Err(LineCheckError::ImproperlyFormatted), + } } - if !SUPPORTED_ALGORITHMS.contains(&algorithm.as_str()) { + if !SUPPORTED_ALGORITHMS.contains(&line_algo.as_str()) { // Not supported algo, leave early return Err(LineCheckError::ImproperlyFormatted); } let bytes = if let Some(bitlen) = line_info.algo_bit_len { - match algorithm.as_str() { + match line_algo.as_str() { ALGORITHM_OPTIONS_BLAKE2B if bitlen % 8 == 0 => Some(bitlen / 8), - ALGORITHM_OPTIONS_SHA3 if [224, 256, 384, 512].contains(&bitlen) => Some(bitlen), + ALGORITHM_OPTIONS_SHA2 | ALGORITHM_OPTIONS_SHA3 + if [224, 256, 384, 512].contains(&bitlen) => + { + Some(bitlen) + } // Either // the algo based line is provided with a bit length // with an algorithm that does not support it (only Blake2B does). @@ -866,14 +882,14 @@ fn identify_algo_name_and_length( // the given length is wrong because it's not a multiple of 8. _ => return Err(LineCheckError::ImproperlyFormatted), } - } else if algorithm == ALGORITHM_OPTIONS_BLAKE2B { + } else if line_algo == ALGORITHM_OPTIONS_BLAKE2B { // Default length with BLAKE2b, Some(64) } else { None }; - Ok((algorithm, bytes)) + Ok((line_algo, bytes)) } /// Given a filename and an algorithm, compute the digest and compare it with diff --git a/tests/by-util/test_cksum.rs b/tests/by-util/test_cksum.rs index e94303a75..afed3d0fe 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -7,6 +7,7 @@ use uutests::at_and_ucmd; use uutests::new_ucmd; use uutests::util::TestScenario; +use uutests::util::log_info; use uutests::util_name; const ALGOS: [&str; 11] = [ @@ -433,6 +434,60 @@ fn test_check_untagged_sha2_multiple_files() { } } +#[test] +fn test_check_sha2_tagged_variant() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + at.touch("f"); + + // SHA2-xxx is an alias to SHAxxx we don't output but we still recognize. + let checksum_lines = [ + ( + "SHA224", + "SHA2-224", + "(f) = d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", + ), + ( + "SHA256", + "SHA2-256", + "(f) = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + ), + ( + "SHA384", + "SHA2-384", + "(f) = 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", + ), + ( + "SHA512", + "SHA2-512", + "(f) = cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + ), + ]; + + for (basic, variant, digest) in checksum_lines { + let stdin = format!("{basic} {digest}"); + log_info("stdin is: ", &stdin); + scene + .ucmd() + .arg("--check") + .arg("--algorithm=sha2") + .pipe_in(stdin) + .succeeds() + .stdout_is("f: OK\n"); + + // Check that the variant works the same + let stdin = format!("{variant} {digest}"); + log_info("stdin is: ", &stdin); + scene + .ucmd() + .arg("--check") + .arg("--algorithm=sha2") + .pipe_in(stdin) + .succeeds() + .stdout_is("f: OK\n"); + } +} + #[test] fn test_sha3_wrong_length() { for l in [0, 13, 819_111_123] {