Skip to content

Commit 56f77f1

Browse files
RenjiSanncakebaker
authored andcommitted
cksum: Refactor Blake length validation
1 parent 572f3a2 commit 56f77f1

6 files changed

Lines changed: 87 additions & 71 deletions

File tree

src/uu/b2sum/src/b2sum.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ use clap::Command;
99

1010
use uu_checksum_common::{standalone_checksum_app_with_length, standalone_with_length_main};
1111

12-
use uucore::checksum::{AlgoKind, calculate_blake_length_str};
12+
use uucore::checksum::{AlgoKind, BlakeLength, parse_blake_length};
1313
use uucore::error::UResult;
1414
use uucore::translate;
1515

1616
#[uucore::main]
1717
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
18-
let calculate_blake2b_length = |s: &str| calculate_blake_length_str(AlgoKind::Blake2b, s);
18+
let calculate_blake2b_length =
19+
|s: &str| parse_blake_length(AlgoKind::Blake2b, BlakeLength::String(s));
1920
standalone_with_length_main(AlgoKind::Blake2b, uu_app(), args, calculate_blake2b_length)
2021
}
2122

src/uu/checksum_common/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub fn standalone_with_length_main(
6363
algo: AlgoKind,
6464
cmd: Command,
6565
args: impl uucore::Args,
66-
validate_len: fn(&str) -> UResult<Option<usize>>,
66+
validate_len: fn(&str) -> UResult<usize>,
6767
) -> UResult<()> {
6868
let matches = uucore::clap_localization::handle_clap_result(cmd, args)?;
6969
let algo = Some(algo);
@@ -72,8 +72,7 @@ pub fn standalone_with_length_main(
7272
.get_one::<String>(options::LENGTH)
7373
.map(String::as_str)
7474
.map(validate_len)
75-
.transpose()?
76-
.flatten();
75+
.transpose()?;
7776

7877
//todo: deduplicate matches.get_flag
7978
let text = !matches.get_flag(options::BINARY);

src/uu/cksum/src/cksum.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use uu_checksum_common::{ChecksumCommand, checksum_main, default_checksum_app, o
1212

1313
use uucore::checksum::compute::OutputFormat;
1414
use uucore::checksum::{
15-
AlgoKind, ChecksumError, calculate_blake_length_str, sanitize_sha2_sha3_length_str,
15+
AlgoKind, BlakeLength, ChecksumError, parse_blake_length, sanitize_sha2_sha3_length_str,
1616
};
1717
use uucore::error::UResult;
1818
use uucore::hardware::{HasHardwareFeatures as _, SimdPolicy};
@@ -69,7 +69,7 @@ fn maybe_sanitize_length(
6969

7070
// For BLAKE, if a length is provided, validate it.
7171
(Some(algo @ (AlgoKind::Blake2b | AlgoKind::Blake3)), Some(len)) => {
72-
calculate_blake_length_str(algo, len)
72+
parse_blake_length(algo, BlakeLength::String(len)).map(Some)
7373
}
7474

7575
// For any other provided algorithm, check if length is 0.

src/uucore/src/lib/features/checksum/mod.rs

Lines changed: 63 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ pub enum SizedAlgoKind {
250250
Sha2(ShaLength),
251251
Sha3(ShaLength),
252252
// Note: we store Blake*'s length as BYTES.
253-
Blake2b(Option<usize>),
254-
Blake3(Option<usize>),
253+
Blake2b(usize),
254+
Blake3(usize),
255255
// Shake* length are stored in bits.
256256
Shake128(Option<usize>),
257257
Shake256(Option<usize>),
@@ -284,22 +284,15 @@ impl SizedAlgoKind {
284284
(ak::Sm3, _) => Ok(Self::Sm3),
285285
(ak::Sha1, _) => Ok(Self::Sha1),
286286

287-
(ak::Blake3, l) => Ok(Self::Blake3(l)),
287+
(ak::Blake2b, l) => Ok(Self::Blake2b(l.unwrap_or(Blake2b::DEFAULT_BYTE_SIZE))),
288+
(ak::Blake3, l) => Ok(Self::Blake3(l.unwrap_or(Blake3::DEFAULT_BYTE_SIZE))),
288289
(ak::Shake128, l) => Ok(Self::Shake128(l)),
289290
(ak::Shake256, l) => Ok(Self::Shake256(l)),
290291
(ak::Sha2, Some(l)) => Ok(Self::Sha2(ShaLength::try_from(l)?)),
291292
(ak::Sha3, Some(l)) => Ok(Self::Sha3(ShaLength::try_from(l)?)),
292293
(algo @ (ak::Sha2 | ak::Sha3), None) => {
293294
Err(ChecksumError::LengthRequiredForSha(algo.to_lowercase().into()).into())
294295
}
295-
// [`calculate_blake2b_length`] expects a length in bits but we
296-
// have a length in bytes.
297-
(algo @ ak::Blake2b, Some(l)) => Ok(Self::Blake2b(calculate_blake_length_str(
298-
algo,
299-
&(8 * l).to_string(),
300-
)?)),
301-
(ak::Blake2b, None) => Ok(Self::Blake2b(None)),
302-
303296
(ak::Sha224, None) => Ok(Self::Sha2(ShaLength::Len224)),
304297
(ak::Sha256, None) => Ok(Self::Sha2(ShaLength::Len256)),
305298
(ak::Sha384, None) => Ok(Self::Sha2(ShaLength::Len384)),
@@ -314,14 +307,9 @@ impl SizedAlgoKind {
314307
Self::Sha1 => "SHA1".into(),
315308
Self::Sha2(len) => format!("SHA{}", len.as_usize()),
316309
Self::Sha3(len) => format!("SHA3-{}", len.as_usize()),
317-
Self::Blake2b(Some(byte_len)) => format!("BLAKE2b-{}", byte_len * 8),
318-
Self::Blake2b(None) => "BLAKE2b".into(),
319-
Self::Blake3(byte_len) => {
320-
format!(
321-
"BLAKE3-{}",
322-
byte_len.unwrap_or(Blake3::DEFAULT_BYTE_SIZE) * 8
323-
)
324-
}
310+
Self::Blake2b(Blake2b::DEFAULT_BYTE_SIZE) => "BLAKE2b".into(),
311+
Self::Blake2b(byte_len) => format!("BLAKE2b-{}", byte_len * 8),
312+
Self::Blake3(byte_len) => format!("BLAKE3-{}", byte_len * 8),
325313
Self::Shake128(opt_bit_len) => format!(
326314
"SHAKE128-{}",
327315
opt_bit_len.unwrap_or(Shake128::DEFAULT_BIT_SIZE)
@@ -354,12 +342,8 @@ impl SizedAlgoKind {
354342
Self::Sha3(Len256) => Box::new(Sha3_256::default()),
355343
Self::Sha3(Len384) => Box::new(Sha3_384::default()),
356344
Self::Sha3(Len512) => Box::new(Sha3_512::default()),
357-
Self::Blake2b(len_opt) => {
358-
Box::new(len_opt.map(Blake2b::with_output_bytes).unwrap_or_default())
359-
}
360-
Self::Blake3(len_opt) => {
361-
Box::new(len_opt.map(Blake3::with_output_bytes).unwrap_or_default())
362-
}
345+
Self::Blake2b(len) => Box::new(Blake2b::with_output_bytes(*len)),
346+
Self::Blake3(len) => Box::new(Blake3::with_output_bytes(*len)),
363347
Self::Shake128(len_opt) => {
364348
Box::new(len_opt.map(Shake128::with_output_bits).unwrap_or_default())
365349
}
@@ -378,10 +362,10 @@ impl SizedAlgoKind {
378362
Self::Md5 => 128,
379363
Self::Sm3 => 512,
380364
Self::Sha1 => 160,
381-
Self::Blake3(len) => len.unwrap_or(Blake3::DEFAULT_BYTE_SIZE) * 8,
382365
Self::Sha2(len) => len.as_usize(),
383366
Self::Sha3(len) => len.as_usize(),
384-
Self::Blake2b(len) => len.unwrap_or(Blake2b::DEFAULT_BYTE_SIZE * 8),
367+
Self::Blake2b(len) => len * 8,
368+
Self::Blake3(len) => len * 8,
385369
Self::Shake128(len) => len.unwrap_or(Shake128::DEFAULT_BIT_SIZE),
386370
Self::Shake256(len) => len.unwrap_or(Shake256::DEFAULT_BIT_SIZE),
387371
}
@@ -495,37 +479,57 @@ pub fn digest_reader<T: Read>(
495479
Ok((digest.result(), output_size))
496480
}
497481

498-
/// Calculates the BYTE length of the digest.
499-
pub fn calculate_blake_length_str(algo: AlgoKind, bit_length: &str) -> UResult<Option<usize>> {
500-
debug_assert!(matches!(algo, AlgoKind::Blake2b | AlgoKind::Blake3));
482+
pub enum BlakeLength<'s> {
483+
Int(usize),
484+
String(&'s str),
485+
}
501486

502-
// Blake2b's length is parsed in an u64.
503-
match bit_length.parse::<usize>() {
504-
Ok(0) => Ok(None),
487+
/// Expects a size in BITS, either as a string or int, and returns it as a BYTE
488+
/// length.
489+
///
490+
/// Note: when the input is a string, validation may print error messages.
491+
/// Note: when the algo is Blake2b, values that are above 512
492+
/// (Blake2b::DEFAULT_BIT_SIZE) are errors.
493+
pub fn parse_blake_length(algo: AlgoKind, bit_length: BlakeLength<'_>) -> UResult<usize> {
494+
debug_assert!(matches!(algo, AlgoKind::Blake2b | AlgoKind::Blake3));
505495

506-
// Error cases
507-
Ok(n) if n > 512 && algo == AlgoKind::Blake2b => {
508-
show_error!("{}", ChecksumError::InvalidLength(bit_length.into()));
509-
Err(ChecksumError::LengthTooBigForBlake(algo.to_uppercase().into()).into())
510-
}
511-
Err(e) if *e.kind() == IntErrorKind::PosOverflow => {
512-
show_error!("{}", ChecksumError::InvalidLength(bit_length.into()));
513-
Err(ChecksumError::LengthTooBigForBlake(algo.to_uppercase().into()).into())
496+
let print_error = || {
497+
if let BlakeLength::String(s) = bit_length {
498+
show_error!("{}", ChecksumError::InvalidLength(s.to_string()));
514499
}
515-
Err(_) => Err(ChecksumError::InvalidLength(bit_length.into()).into()),
500+
};
516501

517-
Ok(n) if n % 8 != 0 => {
518-
show_error!("{}", ChecksumError::InvalidLength(bit_length.into()));
519-
Err(ChecksumError::LengthNotMultipleOf8.into())
520-
}
502+
let n = match bit_length {
503+
BlakeLength::Int(i) => i,
504+
BlakeLength::String(s) => s.parse::<usize>().map_err(|e| {
505+
if *e.kind() == IntErrorKind::PosOverflow {
506+
print_error();
507+
ChecksumError::LengthTooBigForBlake(algo.to_uppercase().into())
508+
} else {
509+
ChecksumError::InvalidLength(s.to_string())
510+
}
511+
})?,
512+
};
521513

522-
// Valid cases
514+
if n == 0 {
515+
return Ok(match algo {
516+
AlgoKind::Blake2b => Blake2b::DEFAULT_BYTE_SIZE,
517+
AlgoKind::Blake3 => Blake3::DEFAULT_BYTE_SIZE,
518+
_ => unreachable!(),
519+
});
520+
}
521+
522+
if algo == AlgoKind::Blake2b && n > Blake2b::DEFAULT_BIT_SIZE {
523+
print_error();
524+
return Err(ChecksumError::LengthTooBigForBlake(algo.to_uppercase().into()).into());
525+
}
523526

524-
// When length is 512, it is blake2b's default. So, don't show it
525-
Ok(512) => Ok(None),
526-
// Divide by 8, as our blake2b implementation expects bytes instead of bits.
527-
Ok(n) => Ok(Some(n / 8)),
527+
if n % 8 != 0 {
528+
print_error();
529+
return Err(ChecksumError::LengthNotMultipleOf8.into());
528530
}
531+
532+
Ok(n / 8)
529533
}
530534

531535
pub fn validate_sha2_sha3_length(algo_name: AlgoKind, length: Option<usize>) -> UResult<ShaLength> {
@@ -644,18 +648,18 @@ mod tests {
644648
#[test]
645649
fn test_calculate_blake2b_length() {
646650
assert_eq!(
647-
calculate_blake_length_str(AlgoKind::Blake2b, "0").unwrap(),
648-
None
651+
parse_blake_length(AlgoKind::Blake2b, BlakeLength::String("0")).unwrap(),
652+
Blake2b::DEFAULT_BYTE_SIZE
649653
);
650-
assert!(calculate_blake_length_str(AlgoKind::Blake2b, "10").is_err());
651-
assert!(calculate_blake_length_str(AlgoKind::Blake2b, "520").is_err());
654+
assert!(parse_blake_length(AlgoKind::Blake2b, BlakeLength::String("10")).is_err());
655+
assert!(parse_blake_length(AlgoKind::Blake2b, BlakeLength::String("520")).is_err());
652656
assert_eq!(
653-
calculate_blake_length_str(AlgoKind::Blake2b, "512").unwrap(),
654-
None
657+
parse_blake_length(AlgoKind::Blake2b, BlakeLength::String("512")).unwrap(),
658+
Blake2b::DEFAULT_BYTE_SIZE
655659
);
656660
assert_eq!(
657-
calculate_blake_length_str(AlgoKind::Blake2b, "256").unwrap(),
658-
Some(32)
661+
parse_blake_length(AlgoKind::Blake2b, BlakeLength::String("256")).unwrap(),
662+
32
659663
);
660664
}
661665
}

src/uucore/src/lib/features/checksum/validate.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ use std::io::{self, BufReader, Read, Write, stderr, stdin};
1515
use os_display::Quotable;
1616

1717
use crate::checksum::{
18-
AlgoKind, ChecksumError, ReadingMode, SizedAlgoKind, digest_reader, unescape_filename,
18+
AlgoKind, BlakeLength, ChecksumError, ReadingMode, SizedAlgoKind, digest_reader,
19+
parse_blake_length, unescape_filename,
1920
};
2021
use crate::error::{FromIo, UError, UIoError, UResult, USimpleError};
2122
use crate::quoting_style::{QuotingStyle, locale_aware_escape_name};
22-
use crate::sum::{self, DigestOutput};
23+
use crate::sum::{self, Blake2b, Blake3, DigestOutput};
2324
use crate::{
2425
os_str_as_bytes, os_str_from_bytes, read_os_string_lines, show, show_warning_caps, translate,
2526
};
@@ -637,7 +638,12 @@ fn identify_algo_name_and_length(
637638

638639
let bytes = if let Some(bitlen) = line_info.algo_bit_len {
639640
match line_algo {
640-
ak::Blake2b | ak::Blake3 if bitlen % 8 == 0 => Some(bitlen / 8),
641+
algo @ (ak::Blake2b | ak::Blake3) => {
642+
match parse_blake_length(algo, BlakeLength::Int(bitlen)) {
643+
Ok(len) => Some(len),
644+
Err(_) => return Err(LineCheckError::ImproperlyFormatted),
645+
}
646+
}
641647
ak::Sha2 | ak::Sha3 if [224, 256, 384, 512].contains(&bitlen) => Some(bitlen),
642648
ak::Shake128 | ak::Shake256 => Some(bitlen),
643649
// Either
@@ -653,10 +659,10 @@ fn identify_algo_name_and_length(
653659
}
654660
} else if line_algo == ak::Blake2b {
655661
// Default length with BLAKE2b,
656-
Some(64)
662+
Some(Blake2b::DEFAULT_BYTE_SIZE)
657663
} else if line_algo == ak::Blake3 {
658664
// Default length with BLAKE3,
659-
Some(32)
665+
Some(Blake3::DEFAULT_BYTE_SIZE)
660666
} else {
661667
None
662668
};

src/uucore/src/lib/features/sum.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,15 @@ pub struct Blake2b {
8383

8484
impl Blake2b {
8585
pub const DEFAULT_BYTE_SIZE: usize = 64;
86+
pub const DEFAULT_BIT_SIZE: usize = Self::DEFAULT_BYTE_SIZE * 8;
8687

8788
/// Return a new Blake2b instance with a custom output bytes length
8889
pub fn with_output_bytes(output_bytes: usize) -> Self {
90+
debug_assert!(
91+
output_bytes <= Self::DEFAULT_BYTE_SIZE,
92+
"GNU doesn't accept BLAKE2b bigger than 64 bytes long"
93+
);
94+
8995
let mut params = blake2b_simd::Params::new();
9096
params.hash_length(output_bytes);
9197

0 commit comments

Comments
 (0)