Skip to content

diff: prevent --tabsize from crashing on huge values - #292

Open
sap1110 wants to merge 1 commit into
uutils:mainfrom
sap1110:diff-huge-tabsize
Open

sap1110 wants to merge 1 commit into
uutils:mainfrom
sap1110:diff-huge-tabsize

Conversation

@sap1110

@sap1110 sap1110 commented Sep 28, 2026

Copy link
Copy Markdown

Fixed an issue where passing an extremely large value to --tabsize could cause diff to crash.

Added an upper limit matching GNU diff.
Values above the limit now return a normal invalid tabsize error.
Added tests for the boundary values and a large --tabsize case.

This keeps the behavior consistent with GNU diff and prevents the crash.

Huge values below the limit (like 2^62) are still accepted, same as GNU, and can still run out of memory. Handling that would need the diff output to be fallible. Let me know if you want that too.

Closes #286

A huge --tabsize was accepted and then used to size the tab expansion
buffer, so the first tab in the input made diff overflow or abort on
allocation failure. Reject values above isize::MAX - 3 with
"invalid tabsize" and exit status 2, as GNU diff does.
Comment thread src/params.rs
use regex::Regex;

/// Largest value accepted for `--tabsize`, matching GNU diff.
const MAX_TABSIZE: usize = isize::MAX as usize - 3;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how did you get - 3?
it's not in the manual, so where does this value come from?

Comment thread src/params.rs
num
}
Err(_) => return Err(format!("invalid tabsize «{tabsize_str}»")),
Ok(num) if num != 0 && num <= MAX_TABSIZE => num,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't fix the crash, it just moves it
-t --tabsize=9223372036854775804 with a tab in the input still aborts in do_expand_tabs (with_capacity + ntabs * (tabsize - 1) overflow)
could you please fix do_expand_tabs instead (no huge preallocation, write the spaces as a stream)?

Comment thread tests/integration.rs
if !option.is_empty() {
cmd.arg(option);
}
cmd.arg("-t")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is -t needed here?

Comment thread tests/integration.rs
file1.write_all("\tx\n".as_bytes())?;
let mut file2 = NamedTempFile::new()?;
file2.write_all("y\n".as_bytes())?;
for option in ["", "-u", "-c"] {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the value is rejected while parsing, so looping over the formats doesn't test anything more, no?
please add a test with a value below the limit and a tab in the input, that's the one that crashes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

diff: -t --tabsize=<huge> aborts in do_expand_tabs

2 participants