Skip to content

Commit

Permalink
hashsum: also escape/unescape files with checks
Browse files Browse the repository at this point in the history
Should fix tests/cksum/md5sum-bsd.sh
  • Loading branch information
sylvestre committed Jan 21, 2024
1 parent 0b5b55e commit f8a0be0
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 11 deletions.
36 changes: 25 additions & 11 deletions src/uu/hashsum/src/hashsum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,8 @@ where
}
let mut gnu_re = gnu_re_template(&bytes_marker, r"(?P<binary>[ \*])?")?;
let bsd_re = Regex::new(&format!(
r"^{algorithm} \((?P<fileName>.*)\) = (?P<digest>[a-fA-F0-9]{digest_size})",
// it can start with \
r"^(|\\){algorithm} \((?P<fileName>.*)\) = (?P<digest>[a-fA-F0-9]{digest_size})",
algorithm = options.algoname,
digest_size = bytes_marker,
))
Expand Down Expand Up @@ -701,7 +702,8 @@ where
}
},
};
let f = match File::open(ck_filename.clone()) {
let (ck_filename_unescaped, prefix) = unescape_filename(&ck_filename);
let f = match File::open(ck_filename_unescaped) {
Err(_) => {
failed_open_file += 1;
println!(
Expand Down Expand Up @@ -734,11 +736,11 @@ where
// easier (and more important) on Unix than on Windows.
if sum == real_sum {
if !options.quiet {
println!("{ck_filename}: OK");
println!("{prefix}{ck_filename}: OK");
}
} else {
if !options.status {
println!("{ck_filename}: FAILED");
println!("{prefix}{ck_filename}: FAILED");

Check warning on line 743 in src/uu/hashsum/src/hashsum.rs

View check run for this annotation

Codecov / codecov/patch

src/uu/hashsum/src/hashsum.rs#L743

Added line #L743 was not covered by tests
}
failed_cksum += 1;
}
Expand All @@ -751,16 +753,19 @@ where
options.output_bits,
)
.map_err_context(|| "failed to read input".to_string())?;
let (escaped_filename, prefix) = escape_filename(filename);
if options.tag {
println!("{} ({}) = {}", options.algoname, filename.display(), sum);
println!(
"{}{} ({}) = {}",
prefix, options.algoname, escaped_filename, sum
);
} else if options.nonames {
println!("{sum}");
} else if options.zero {
// with zero, we don't escape the filename
print!("{} {}{}\0", sum, binary_marker, filename.display());
} else {
let (filename, has_prefix) = escape_filename(filename);
let prefix = if has_prefix { "\\" } else { "" };
println!("{}{} {}{}", prefix, sum, binary_marker, filename);
println!("{}{} {}{}", prefix, sum, binary_marker, escaped_filename);
}
}
}
Expand All @@ -785,14 +790,23 @@ where
Ok(())
}

fn escape_filename(filename: &Path) -> (String, bool) {
fn unescape_filename(filename: &str) -> (String, &'static str) {
let escaped = filename
.replace("\\\\", "\\")
.replace("\\n", "\n")
.replace("\\r", "\r");
let prefix = if escaped == filename { "" } else { "\\" };
(escaped, prefix)
}

fn escape_filename(filename: &Path) -> (String, &'static str) {
let original = filename.as_os_str().to_string_lossy();
let escaped = original
.replace('\\', "\\\\")
.replace('\n', "\\n")
.replace('\r', "\\r");
let has_changed = escaped != original;
(escaped, has_changed)
let prefix = if escaped == original { "" } else { "\\" };
(escaped, prefix)
}

fn digest_reader<T: Read>(
Expand Down
44 changes: 44 additions & 0 deletions tests/by-util/test_hashsum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,3 +392,47 @@ fn test_with_escape_filename() {
assert!(stdout.starts_with('\\'));
assert!(stdout.trim().ends_with("a\\nb"));
}

#[test]
#[cfg(not(windows))]
fn test_with_escape_filename_zero_text() {
let scene = TestScenario::new(util_name!());

let at = &scene.fixtures;
let filename = "a\nb";
at.touch(filename);
let result = scene
.ccmd("md5sum")
.arg("--text")
.arg("--zero")
.arg(filename)
.succeeds();
let stdout = result.stdout_str();
println!("stdout {}", stdout);
assert!(!stdout.starts_with('\\'));
assert!(stdout.contains("a\nb"));
}

#[test]
#[cfg(not(windows))]
fn test_check_with_escape_filename() {
let scene = TestScenario::new(util_name!());

let at = &scene.fixtures;

let filename = "a\nb";
at.touch(filename);
let result = scene.ccmd("md5sum").arg("--tag").arg(filename).succeeds();
let stdout = result.stdout_str();
println!("stdout {}", stdout);
assert!(stdout.starts_with("\\MD5"));
assert!(stdout.contains("a\\nb"));
at.write("check.md5", stdout);
let result = scene
.ccmd("md5sum")
.arg("--strict")
.arg("-c")
.arg("check.md5")
.succeeds();
assert!(result.stdout_str().contains("OK"));
}

0 comments on commit f8a0be0

Please sign in to comment.