SHA256
1
0
forked from pool/sed
sed/sed-fix-overlapping-address-ranges.patch

86 lines
3.1 KiB
Diff
Raw Normal View History

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;