diff --git a/src/cmp.rs b/src/cmp.rs index e3534a0..0f7250c 100644 --- a/src/cmp.rs +++ b/src/cmp.rs @@ -607,7 +607,7 @@ fn format_verbose_difference( } else { // "{:>width$} {:>3o} {:>3o}" let at_byte_str = at_byte_buf.format(at_byte); - let at_byte_padding = offset_width - at_byte_str.len(); + let at_byte_padding = offset_width.saturating_sub(at_byte_str.len()); for _ in 0..at_byte_padding { output.push(b' ') diff --git a/tests/integration.rs b/tests/integration.rs index e6b14e2..12aabb8 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -348,6 +348,26 @@ mod diff { mod cmp { use super::*; + // A file whose metadata length is 0 but which still yields bytes (/dev/zero) + // collapses the offset column to two characters, so the padding subtraction + // underflowed once the running offset reached three digits. + #[test] + #[cfg(unix)] + fn cmp_verbose_zero_length_metadata() -> Result<(), Box> { + let mut file = NamedTempFile::new()?; + file.write_all(&[0xffu8; 150])?; + + let mut cmd = cargo_bin_cmd!("diffutils"); + cmd.arg("cmp") + .arg("--verbose") + .arg("/dev/zero") + .arg(file.path()); + cmd.assert() + .code(predicate::eq(1)) + .stdout(predicate::str::contains("150 0 377")); + Ok(()) + } + #[test] fn cmp_incompatible_params() -> Result<(), Box> { let mut cmd = cargo_bin_cmd!("diffutils");