Summary
bat --line-range :-N (an offset-from-end range) with a very large N aborts with capacity overflow (exit 101). The offset is parsed as an unbounded usize and flows directly into VecDeque::with_capacity, which aborts when the requested capacity exceeds what the allocator can represent.
What steps will reproduce the bug?
$ printf 'l1\nl2\n' | bat --no-config --paging=never --line-range ':-18446744073709551614' -
thread 'main' panicked at src/controller.rs:264:62:
capacity overflow
$ echo $?
101
:-N is the "N lines from the end" range syntax (RangeBound::OffsetFromEnd). N == 18446744073709551614 is usize::MAX - 1, which makes the buffer size usize::MAX; VecDeque::with_capacity(usize::MAX) aborts. N == usize::MAX (…615) instead overflows the + 1 — silent wrap in release, an attempt to add with overflow panic only under -C overflow-checks.
What did you expect to happen instead?
An out-of-range line offset should be rejected or clamped (bat already validates other numeric args), not turned into an allocation request that aborts the process.
Root cause
Controller::print_file_ranges (src/controller.rs:262-264):
// Buffer needs to be 1 greater than the offset to have a look-ahead line for EOF
let buffer_size: usize = line_ranges.largest_offset_from_end() + 1; // :262
let mut buffered_lines: VecDeque<(Vec<u8>, usize)> = VecDeque::with_capacity(buffer_size); // :264
largest_offset_from_end() returns the raw offset parsed from --line-range :-N (src/line_range.rs: range_raw[2..].parse() into RangeBound::OffsetFromEnd, with no upper bound). The buffer is sized to the offset before a single line is read, so a caller-controlled number becomes the VecDeque capacity:
N == usize::MAX - 1 → buffer_size == usize::MAX → with_capacity aborts (capacity overflow), release and debug alike (this report's repro).
N == usize::MAX → buffer_size overflows + 1; release wraps to 0 (no panic), debug aborts under overflow-checks (site :262).
Environment
bat 0.26.1 (commit af1f53d9), rustc 1.90 (stable), Ubuntu 20.04 x86_64
Summary
bat --line-range :-N(an offset-from-end range) with a very largeNaborts withcapacity overflow(exit 101). The offset is parsed as an unboundedusizeand flows directly intoVecDeque::with_capacity, which aborts when the requested capacity exceeds what the allocator can represent.What steps will reproduce the bug?
:-Nis the "N lines from the end" range syntax (RangeBound::OffsetFromEnd).N == 18446744073709551614isusize::MAX - 1, which makes the buffer sizeusize::MAX;VecDeque::with_capacity(usize::MAX)aborts.N == usize::MAX(…615) instead overflows the+ 1— silent wrap in release, anattempt to add with overflowpanic only under-C overflow-checks.What did you expect to happen instead?
An out-of-range line offset should be rejected or clamped (bat already validates other numeric args), not turned into an allocation request that aborts the process.
Root cause
Controller::print_file_ranges(src/controller.rs:262-264):largest_offset_from_end()returns the raw offset parsed from--line-range :-N(src/line_range.rs:range_raw[2..].parse()intoRangeBound::OffsetFromEnd, with no upper bound). The buffer is sized to the offset before a single line is read, so a caller-controlled number becomes theVecDequecapacity:N == usize::MAX - 1→buffer_size == usize::MAX→with_capacityaborts (capacity overflow), release and debug alike (this report's repro).N == usize::MAX→buffer_sizeoverflows+ 1; release wraps to0(no panic), debug aborts under overflow-checks (site:262).Environment
bat
0.26.1(commitaf1f53d9), rustc 1.90 (stable), Ubuntu 20.04 x86_64