86 lines
3.1 KiB
Diff
86 lines
3.1 KiB
Diff
|
This is a backport of the fix itself.
|
||
|
|
||
|
From 4c75f64068a7e1446c9aa6ae8f764e0ebddd67ef Mon Sep 17 00:00:00 2001
|
||
|
From: Norihiro Tanaka <noritnk@kcn.ne.jp>
|
||
|
Date: Fri, 20 Feb 2015 01:54:35 +0900
|
||
|
Subject: [PATCH 81/92] sed: fix mishandling of overlapping address ranges
|
||
|
|
||
|
When the line number ranges of two or more editing commands overlap,
|
||
|
sed applies all commands but the first to a line that is just beyond
|
||
|
the union of all ranges. E.g., with this command,
|
||
|
seq 9|sed '2,7d;3,6d', sed would mistakenly delete line 8.
|
||
|
|
||
|
* sed/execute.c (match_an_address_p) [ADDR_IS_NUM]: Make this
|
||
|
function work also in this case.
|
||
|
(match_address_p): Move the ADDR_IS_NUM +
|
||
|
...->line_number == ...->addr_number comparison "up" into
|
||
|
match_an_address_p, so we can hoist two similar if/return
|
||
|
blocks out of "if" and "else" branches.
|
||
|
Change so that this function returns false when the current
|
||
|
line number is outside the specified range.
|
||
|
* testsuite/range-overlap.sh: New file, to test for this.
|
||
|
* testsuite/Makefile.am (T): Add it to the list.
|
||
|
* NEWS (Bug fixes): Mention it.
|
||
|
Reported as http://bugs.gnu.org/19899
|
||
|
---
|
||
|
NEWS | 15 +++++++++++++++
|
||
|
sed/execute.c | 16 ++++++++--------
|
||
|
testsuite/Makefile.am | 3 ++-
|
||
|
testsuite/range-overlap.sh | 34 ++++++++++++++++++++++++++++++++++
|
||
|
4 files changed, 59 insertions(+), 9 deletions(-)
|
||
|
create mode 100755 testsuite/range-overlap.sh
|
||
|
|
||
|
Index: sed-4.2.2/sed/execute.c
|
||
|
===================================================================
|
||
|
--- sed-4.2.2.orig/sed/execute.c
|
||
|
+++ sed-4.2.2/sed/execute.c
|
||
|
@@ -860,8 +860,10 @@ match_an_address_p(addr, input)
|
||
|
case ADDR_IS_LAST:
|
||
|
return test_eof(input);
|
||
|
|
||
|
- /* ADDR_IS_NUM is handled in match_address_p. */
|
||
|
case ADDR_IS_NUM:
|
||
|
+ /* reminder: these are only meaningful for a1 addresses */
|
||
|
+ return (addr->addr_number == input->line_number);
|
||
|
+
|
||
|
default:
|
||
|
panic("INTERNAL ERROR: bad address type");
|
||
|
}
|
||
|
@@ -881,23 +883,20 @@ match_address_p(cmd, input)
|
||
|
|
||
|
if (cmd->range_state != RANGE_ACTIVE)
|
||
|
{
|
||
|
+ if (!cmd->a2)
|
||
|
+ return match_an_address_p(cmd->a1, input);
|
||
|
+
|
||
|
/* Find if we are going to activate a range. Handle ADDR_IS_NUM
|
||
|
specially: it represent an "absolute" state, it should not
|
||
|
be computed like regexes. */
|
||
|
if (cmd->a1->addr_type == ADDR_IS_NUM)
|
||
|
{
|
||
|
- if (!cmd->a2)
|
||
|
- return (input->line_number == cmd->a1->addr_number);
|
||
|
-
|
||
|
if (cmd->range_state == RANGE_CLOSED
|
||
|
|| input->line_number < cmd->a1->addr_number)
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
- if (!cmd->a2)
|
||
|
- return match_an_address_p(cmd->a1, input);
|
||
|
-
|
||
|
if (!match_an_address_p(cmd->a1, input))
|
||
|
return false;
|
||
|
}
|
||
|
@@ -913,7 +912,8 @@ match_address_p(cmd, input)
|
||
|
/* Same handling as below, but always include at least one line. */
|
||
|
if (input->line_number >= cmd->a2->addr_number)
|
||
|
cmd->range_state = RANGE_CLOSED;
|
||
|
- return true;
|
||
|
+ return (input->line_number <= cmd->a2->addr_number
|
||
|
+ || match_an_address_p(cmd->a1, input));
|
||
|
case ADDR_IS_STEP:
|
||
|
cmd->a2->addr_number = input->line_number + cmd->a2->addr_step;
|
||
|
return true;
|