Skip to content

csplit: a negative offset may not cross the split start - #14407

Open
Socialpranker wants to merge 1 commit into
uutils:mainfrom
Socialpranker:csplit-negative-offset-segment-bound
Open

csplit: a negative offset may not cross the split start#14407
Socialpranker wants to merge 1 commit into
uutils:mainfrom
Socialpranker:csplit-negative-offset-segment-bound

Conversation

@Socialpranker

Copy link
Copy Markdown
Contributor

For /re/-N, GNU requires the target line (the match minus N) to be at or
after the first line of the current split; otherwise it fails:

$ seq 50 | csplit - '/3$/-3'      # GNU: 'line number out of range', status 1, no xx* files
$ seq 50 | csplit - '/3$/-3'      # uutils, before: splits at line 0, status 0
$ seq 50 | csplit - '/10$/' '/12$/-3'   # same, for a split that does not start at line 1

uutils only checked that the target does not precede the start of the input
(buffer_len() < offset), so a negative offset could silently reach back into a
previous split. do_to_match now counts the lines of the current split read
before the match (the ones carried over in the buffer plus the ones read in the
loop) and reports the existing LineOutOfRange error when the offset exceeds
them. The old buffer-length check is the same test in the special case of the
first split, so it is dropped. Target line exactly at the split start stays a
valid (empty) split. %re%-N, {N} repetitions, -k, -z, -s and
--suppress-matched all follow.

Testing

  • 6 new tests in tests/by-util/test_csplit.rs (exact stderr, status, and the
    absence/presence of the split files). Mutation-checked: reverting
    csplit.rs alone fails 4 of them.
  • cargo test --features csplit --test tests test_csplit: 95 passed, 0 failed.
  • cargo clippy -p uu_csplit --all-targets -- -D warnings and cargo fmt --check: clean.
  • Differential run against GNU coreutils 9.11 over 27 csplit invocations
    (negative offsets shorter/equal/longer than the distance to the split start,
    in the first, second and third split, with the options above, plus /re/+N
    and %re%-N for contrast): 12 mismatches before, 0 after.
  • The behavior was established by running the installed GNU 9.11 binary as a
    black box; I did not read GNU coreutils source.

Disclosure

Prepared with AI assistance (Claude Opus 5, via Claude Code), per the AI policy
in CONTRIBUTING.md. All testing was run locally.

@github-actions

github-actions Bot commented Sep 6, 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)
Note: The gnu test tests/dd/no-allocate is now being skipped but was previously passing.
Congrats! The gnu test tests/tail/pipe-f is now passing!

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.

1 participant