Skip to content

sed: don't restart a numeric range when a branch or D revisits its line - #675

Open
sarankumar1325 wants to merge 1 commit into
uutils:mainfrom
sarankumar1325:fix-numeric-range-restart
Open

sarankumar1325 wants to merge 1 commit into
uutils:mainfrom
sarankumar1325:fix-numeric-range-restart

Conversation

@sarankumar1325

Copy link
Copy Markdown
Contributor

Fixes #648.

In applies(), a numeric first address equal to the current line went through match_address, which is true every time the line is re-evaluated. So a range that starts and ends on the same line was selected again after each backward b/t branch or D restart, and :y;2,+0by never terminated.

Changes:

  • A numeric start equal to the current line now also needs !command.range_started. It's the same rule the linenum > n arm already uses, so a line-number range is entered only once per input (or per file with -s/-i, where reset_latched_address_ranges clears it).
  • A $ end that already matches on the start line (N,$ when N is the last line) closes the range there instead of latching it, so revisiting the line doesn't select it a second time.

Checked against GNU sed 4.9 (same output now):

script input GNU / this PR main
:a;2,+0{s/x/y/;ta} (also 2,2, 2,0, 2,~0, 2,1, 2,$) a\nxxx a\nyxx a\nyyy
:y;2,+0by 1\n2\n3 1\n2\n3 hangs
:a;2,/x/{s/x/y/;ta} a\nxxx\nxx a\nyyx\nxx a\nyyy\nyx

Also unchanged against GNU: 2,3p, 2,2p;2,1p, 1,$p, /b/,$p, $!N;3,$P;D, and 2,$p and a branching 2,$ loop over two files with and without -s.

Tests (tests/by-util/test_sed.rs): test_numeric_range_not_restarted_by_branch (6 scripts), test_numeric_range_regex_end_not_restarted_by_branch and test_numeric_range_branch_terminates (5 s timeout) fail on main and pass with this change. test_numeric_range_not_restarted_by_d_restart passes on both and guards the D path. cargo fmt --check and cargo clippy --all-targets -- -D warnings are clean. cargo test: everything passes except test_invalid_unicode_escape_does_not_panic, the intermittent broken-pipe failure that #674 fixes (it fails on main too).

Not in this PR: GNU also stops re-selecting a range's last line once it has closed on it (:a;2,3{s/x/y/;ta} gives yx on line 3 under GNU, yy here, both before and after this change). That's the active-range path, not the restart this issue is about. I can send it separately if you want it.

I used an AI assistant for this change and reviewed the code and tests myself.

A range whose first address is a line number and that ends on that same
line (2,+0, 2,2, 2,0, 2,~0, 2,1, 2,/re/ matching line 2, 2,$ on the last
line) was selected again each time a backward b/t branch or a D restart
re-evaluated the command on that line, so ':y;2,+0by' never terminated.
A numeric start equal to the current line now also requires that the
range hasn't been entered yet, and a $ end that matches where the range
starts closes it there.

Fixes uutils#648
Copilot AI balanced review requested due to automatic review settings November 11, 2026 02:59

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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.

@codspeed

codspeed Bot commented Nov 11, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 2.81%

1 warning

⚠️ 1 benchmark is dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚡ 1 improved benchmark
✅ 10 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
⚡ no_op_short 2.2 s 2.1 s +2.81%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing sarankumar1325:fix-numeric-range-restart (817be59) with main (cab1c6e)

Open in CodSpeed

@codecov

codecov Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.39%. Comparing base (cab1c6e) to head (817be59).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #675   +/-   ##
=======================================
  Coverage   95.39%   95.39%           
=======================================
  Files          14       14           
  Lines        7665     7670    +5     
  Branches      457      459    +2     
=======================================
+ Hits         7312     7317    +5     
  Misses        352      352           
  Partials        1        1           
Flag Coverage Δ
macos_latest 96.86% <100.00%> (+<0.01%) ⬆️
ubuntu_latest 96.79% <100.00%> (+<0.01%) ⬆️
windows_latest 0.00% <0.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

sed - a range like 2,+0 restarts when a backward branch or D revisits its line (infinite loop)

2 participants