uutils / uutils/coreutils

csplit: panic on overflow in `{N}` repetition count and `/regex/OFF` offset

Open Beginner friendly
#12,495 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

U - csplit
Dominant language
Rust
Stars
24.1k
Forks
2k
Avg merge
1d 5h
Merged PRs (30d)
365

Description

Affects: uutils/coreutils main (verified at commit aaf4a353c, 2026-05-28)
Severity: panic + abort on user-supplied input that GNU csplit rejects cleanly

Summary

csplit panics with a Rust backtrace instead of returning a clean error when
the user supplies a pattern argument whose embedded integer exceeds the target
type's range. Two distinct sites in src/uu/csplit/src/patterns.rs call
.unwrap() on a str::parse::<usize>() / str::parse::<i32>():

  • line 123 — the {N} repetition count
  • line 136 — the /regex/OFF (and %regex%OFF) line offset

Reproduction

$ csplit - 1 '{99999999999999999999999999999999}' < /etc/hostname
thread 'main' panicked at src/uu/csplit/src/patterns.rs:123:83:
called `Result::unwrap()` on an `Err` value: ParseIntError { kind: PosOverflow }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Aborted (core dumped)
$ echo $?
134

$ csplit - '/x/-2147483649' < /etc/hostname
thread 'main' panicked at src/uu/csplit/src/patterns.rs:136:47:
called `Result::unwrap()` on an `Err` value: ParseIntError { kind: NegOverflow }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Aborted (core dumped)
$ echo $?
134

GNU coreutils 8.30 on the same inputs:

$ /usr/bin/csplit - 1 '{99999999999999999999999999999999}' < /etc/hostname
csplit: '{99999999999999999999999999999999'}: integer required between '{' and '}'
$ echo $?
1

$ /usr/bin/csplit - '/x/-2147483649' < /etc/hostname
csplit: '/x/-2147483649': line number out of range
$ echo $?
1

Offending code

src/uu/csplit/src/patterns.rs

// line 123 — {N} repetition count
if let Some(times) = r.name("TIMES") {
    ExecutePattern::Times(times.as_str().parse::<usize>().unwrap() + 1)
} else { ... }

// line 136 — /regex/OFF offset
let offset = match captures.name("OFFSET") {
    None => 0,
    Some(m) => m.as_str().parse().unwrap(),
};

Both should propagate a CsplitError::InvalidPattern (or a more specific
variant) instead of unwrapping.

Suggested fix

// {N} repetition count
if let Some(times) = r.name("TIMES") {
    let n: usize = times
        .as_str()
        .parse()
        .map_err(|_| CsplitError::InvalidPattern(next_item.to_owned()))?;
    ExecutePattern::Times(n.checked_add(1)
        .ok_or_else(|| CsplitError::InvalidPattern(next_item.to_owned()))?)
} else { ExecutePattern::Always }

// /regex/OFF offset
let offset = match captures.name("OFFSET") {
    None => 0,
    Some(m) => m
        .as_str()
        .parse()
        .map_err(|_| CsplitError::InvalidPattern(arg.to_owned()))?,
};

(The + 1 overflow on usize::MAX does not panic in release builds because
overflow checks are off — but it still produces silently wrong behavior
(Times(0)). The checked_add makes that a clean error in both profiles.)

Found by our static analysis tooling.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/uu/csplit/src/patterns.rs at the {N} repetition-count and /regex/OFF offset parsing sites, then run the two overflow reproductions from the issue. Done means both inputs return a clean csplit error matching the existing invalid-pattern behavior, without a panic or abort; include regression coverage if the surrounding tests support it.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.