Skip to content

pr: arithmetic overflow (overflow-checks) on a huge -N line number or -l lines-per-page #13734

Description

@leeewee

Two of pr's own numeric computations perform unchecked integer arithmetic on user-controlled option values:

  • -n -N <huge> — the running line number is seeded from -N and incremented with line_num += 1, which overflows (attempt to add with overflow).
  • -l <huge> — the page geometry computes content_lines_per_page * columns (with a small column count), which overflows (attempt to multiply with overflow).

Both panic under -C overflow-checks (debug builds, or a release build with overflow-checks on) and abort (exit 134); in a default release build they wrap silently.

Steps to reproduce

$ printf 'l1\nl2\nl3\n' > /tmp/pri

$ pr -n -N 18446744073709551615 /tmp/pri
thread 'main' panicked at src/uu/pr/src/pr.rs:1120:17:
attempt to add with overflow
$ echo $?
134

$ pr -l 9999999999999999999 -3 /tmp/pri
thread 'main' panicked at src/uu/pr/src/pr.rs:1582:9:
attempt to multiply with overflow
$ echo $?
134

GNU behavior

GNU rejects the out-of-range value without a panic.

$ /usr/bin/pr -n -N 18446744073709551615 /tmp/pri ;   
/usr/bin/pr: '-N NUMBER' invalid starting line number: ‘18446744073709551615’: Value too large for defined data type
$ echo $? 
1

$ /usr/bin/pr -l 9999999999999999999 -3 /tmp/pri ; 
/usr/bin/pr: '-l PAGE_LENGTH' invalid number of lines: ‘9999999999999999999’: Value too large for defined data type
$echo $?   
1

Root cause

// src/uu/pr/src/pr.rs:1063   let mut line_num = get_start_line_number(options);  // = -N value
// src/uu/pr/src/pr.rs:1120
line_num += 1;               // overflows when -N is near usize::MAX

Page geometry (pr.rs:1582, sibling check at :1406): lines-per-page (from -l) times the column count is multiplied unchecked — a huge -l overflows it even with the default small column count:

// src/uu/pr/src/pr.rs:1579-1582  (lines_to_read_for_page)
if opts.double_space {
    (content_lines_per_page / 2) * columns
} else {
    content_lines_per_page * columns   // :1582 — overflows for a huge -l * columns
}
// and the same product gates the layout at pr.rs:1406:
//   if !merge && (lines.len() < (content_lines_per_page * columns)) { ... }

(A huge value via the -COLUMN/--column short option also reaches this multiply, but that trigger is the already-filed #12996.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions