Skip to content

fix(ptx): reject --gap-size/--width values exceeding isize::MAX#13216

Open
koopatroopa787 wants to merge 2 commits into
uutils:mainfrom
koopatroopa787:fix-ptx-gap-size-width-overflow
Open

fix(ptx): reject --gap-size/--width values exceeding isize::MAX#13216
koopatroopa787 wants to merge 2 commits into
uutils:mainfrom
koopatroopa787:fix-ptx-gap-size-width-overflow

Conversation

@koopatroopa787

Copy link
Copy Markdown
Contributor

Fixes #13184.

Bug

ptx --gap-size N with N > isize::MAX panics (debug) or produces silent garbage / capacity overflow (release) because the output-chunk sizing math casts the value with as isize, which wraps negative on overflow:

let max_before_size =
    cmp::max(half_line_size as isize - config.gap_size as isize, 0) as usize;

GNU ptx rejects any value above isize::MAX up front:

$ ptx --gap-size 9223372036854775808 in
ptx: invalid gap width: '9223372036854775808'   # exit 1
$ ptx --width 9223372036854775808 in
ptx: invalid line width: '9223372036854775808'  # exit 1

Fix

Add two new PtxError variants (InvalidGapWidth, InvalidLineWidth) and validate the parsed usize against isize::MAX as usize immediately after parsing, before the value is stored in Config. This matches GNU's exact error messages and exit code.

Testing

Added test_gap_size_above_isize_max_is_rejected and test_line_width_above_isize_max_is_rejected. All 45 ptx tests pass; cargo clippy -D warnings and cargo fmt --check clean.

Values above isize::MAX are silently cast to a negative isize when the
output-chunk sizing arithmetic does `value as isize`, wrapping in release
builds (producing garbage output or capacity overflow) and panicking in
debug builds (attempt to subtract with overflow).

GNU ptx rejects any such value up front with "invalid gap width" /
"invalid line width" and exits 1. Match that behaviour by validating the
parsed usize against isize::MAX immediately after parsing, before the
value is stored in Config.

Fixes uutils#13184
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/date/date-locale-hour (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/pr/bounded-memory (fails in this run but passes in the 'main' branch)
Congrats! The gnu test tests/expand/bounded-memory is now passing!
Congrats! The gnu test tests/rm/many-dir-entries-vs-OOM is now passing!

@codspeed-hq

codspeed-hq Bot commented Jun 30, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 132 untouched benchmarks
⏩ 253 skipped benchmarks1


Comparing koopatroopa787:fix-ptx-gap-size-width-overflow (6d93e4e) with main (ef50d8b)

Open in CodSpeed

Footnotes

  1. 253 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@koopatroopa787

Copy link
Copy Markdown
Contributor Author

Gentle ping — CI is green (the 4.67% CodSpeed sort_ascii_c_locale regression appears on multiple unrelated PRs simultaneously and is a benchmark flake, not caused by this change). Happy to rebase or address any reviewer feedback.

Copilot AI review requested due to automatic review settings July 20, 2026 15:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

This PR fixes a crash/overflow bug in ptx when users pass --gap-size or --width values greater than isize::MAX, aligning behavior with GNU ptx by rejecting those inputs early.

Changes:

  • Add PtxError variants for invalid gap width and line width values.
  • Validate parsed --width and --gap-size against isize::MAX before storing in Config.
  • Add regression tests covering values just above isize::MAX for both flags.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
tests/by-util/test_ptx.rs Adds regression tests ensuring oversized --gap-size/--width inputs are rejected.
src/uu/ptx/src/ptx.rs Introduces new error variants and clamps accepted numeric ranges to <= isize::MAX.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/uu/ptx/src/ptx.rs
Comment on lines +253 to +258
let s = matches.get_one::<String>(options::WIDTH).expect(err_msg);
let v: usize = s.parse().map_err(PtxError::ParseError)?;
if v > isize::MAX as usize {
return Err(PtxError::InvalidLineWidth(s.clone()).into());
}
config.line_width = v;
Comment thread src/uu/ptx/src/ptx.rs
Comment on lines +263 to +268
let s = matches.get_one::<String>(options::GAP_SIZE).expect(err_msg);
let v: usize = s.parse().map_err(PtxError::ParseError)?;
if v > isize::MAX as usize {
return Err(PtxError::InvalidGapWidth(s.clone()).into());
}
config.gap_size = v;
Comment thread tests/by-util/test_ptx.rs
Comment on lines +433 to +438
let too_big = format!("{}", isize::MAX as u64 + 1);
new_ucmd!()
.args(&["--gap-size", &too_big])
.pipe_in("hello world\n")
.fails()
.stderr_contains("invalid gap width");
Comment thread tests/by-util/test_ptx.rs
Comment on lines +443 to +448
let too_big = format!("{}", isize::MAX as u64 + 1);
new_ucmd!()
.args(&["--width", &too_big])
.pipe_in("hello world\n")
.fails()
.stderr_contains("invalid line width");
Comment thread src/uu/ptx/src/ptx.rs
Comment on lines +253 to +258
let s = matches.get_one::<String>(options::WIDTH).expect(err_msg);
let v: usize = s.parse().map_err(PtxError::ParseError)?;
if v > isize::MAX as usize {
return Err(PtxError::InvalidLineWidth(s.clone()).into());
}
config.line_width = v;
Comment thread src/uu/ptx/src/ptx.rs
Comment on lines +263 to +268
let s = matches.get_one::<String>(options::GAP_SIZE).expect(err_msg);
let v: usize = s.parse().map_err(PtxError::ParseError)?;
if v > isize::MAX as usize {
return Err(PtxError::InvalidGapWidth(s.clone()).into());
}
config.gap_size = v;
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.

ptx accepts --gap-size/--width value exceeding isize::MAX while GNU ptx rejects

3 participants