Skip to content

Commit 68d0610

Browse files
Pablo Garciasylvestre
authored andcommitted
cmp: use checked subtraction for the verbose offset padding
The --verbose branch of format_verbose_difference padded the byte-offset column with a plain subtraction while the --print-bytes branch above it already used saturating_sub. offset_width is derived from the smaller file's metadata length, so a file reporting length 0 that still yields bytes (/dev/zero) collapses it to 2 and the subtraction underflows once the offset reaches three digits. Fixes #265
1 parent 3b68237 commit 68d0610

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

‎src/cmp.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ fn format_verbose_difference(
607607
} else {
608608
// "{:>width$} {:>3o} {:>3o}"
609609
let at_byte_str = at_byte_buf.format(at_byte);
610-
let at_byte_padding = offset_width - at_byte_str.len();
610+
let at_byte_padding = offset_width.saturating_sub(at_byte_str.len());
611611

612612
for _ in 0..at_byte_padding {
613613
output.push(b' ')

‎tests/integration.rs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,26 @@ mod diff {
348348
mod cmp {
349349
use super::*;
350350

351+
// A file whose metadata length is 0 but which still yields bytes (/dev/zero)
352+
// collapses the offset column to two characters, so the padding subtraction
353+
// underflowed once the running offset reached three digits.
354+
#[test]
355+
#[cfg(unix)]
356+
fn cmp_verbose_zero_length_metadata() -> Result<(), Box<dyn std::error::Error>> {
357+
let mut file = NamedTempFile::new()?;
358+
file.write_all(&[0xffu8; 150])?;
359+
360+
let mut cmd = cargo_bin_cmd!("diffutils");
361+
cmd.arg("cmp")
362+
.arg("--verbose")
363+
.arg("/dev/zero")
364+
.arg(file.path());
365+
cmd.assert()
366+
.code(predicate::eq(1))
367+
.stdout(predicate::str::contains("150 0 377"));
368+
Ok(())
369+
}
370+
351371
#[test]
352372
fn cmp_incompatible_params() -> Result<(), Box<dyn std::error::Error>> {
353373
let mut cmd = cargo_bin_cmd!("diffutils");

0 commit comments

Comments
 (0)