From 8d3c367feed14234089edd58a2b697c0052374c3 Mon Sep 17 00:00:00 2001 From: Norihiro Tanaka Date: Fri, 20 Feb 2015 01:54:35 +0900 Subject: [PATCH] sed: fix mishandle with overwrapped line number addresses When line number addresses are overwrapped in two editing commands, sed always executes for at least one line with the second edition command, even if out of between two addresses. e.g. for '2,7d;3,6d', sed executes for line 8 which should not be executed for. * sed/execute.c (match_an_address_p): Add movement for line number addresses. (match_address_p): Change as not executed if out of between two addresses. * testsuite/overwrap.good, : New file, to test for this. * testsuite/overwrap.inp: New file, to test for this. * testsuite/overwrap.sed: New file, to test for this. * testsuite/Makefile.am (SEDTESTS, EXTRA_DIST): Add a rule for the new test. * testsuite/Makefile.tests: Add a rule for the new test. * NEWS (Bug fixes): Mention it. --- NEWS | 6 ++++++ sed/execute.c | 16 ++++++++-------- testsuite/Makefile.am | 3 ++- testsuite/Makefile.tests | 2 +- testsuite/overwrap.good | 4 ++++ testsuite/overwrap.inp | 10 ++++++++++ testsuite/overwrap.sed | 1 + 7 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 testsuite/overwrap.good create mode 100644 testsuite/overwrap.inp create mode 100644 testsuite/overwrap.sed diff --git a/NEWS b/NEWS index b713b1d..26f70d1 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,12 @@ GNU sed NEWS -*- outline -*- is what stopped working. [bug introduced some time after sed-3.02 and prior to the first sed-4* test release] + When line number addresses are overwrapped in two editing commands, + sed always executes for at least one line with the second edition + command, even if out of between two addresses. e.g. for '2,7d;3,6d', + sed executes for line 8 which should not be executed for. [bug + introduced some time after sed-4.09 and prior to release in sed-4.1] + ** Feature removal The "L" command (format a paragraph like the fmt(1) command would) diff --git a/sed/execute.c b/sed/execute.c index 8510a15..547d3ef 100644 --- a/sed/execute.c +++ b/sed/execute.c @@ -798,8 +798,10 @@ match_an_address_p(struct addr *addr, struct input *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"); } @@ -816,23 +818,20 @@ match_address_p(struct sed_cmd *cmd, struct input *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; } @@ -848,7 +847,8 @@ match_address_p(struct sed_cmd *cmd, struct input *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; diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index 060033b..2895196 100644 --- a/testsuite/Makefile.am +++ b/testsuite/Makefile.am @@ -26,7 +26,7 @@ SEDTESTS += \ insens subwrite writeout readin insert utf8-1 utf8-2 utf8-3 utf8-4 \ badenc inplace-hold brackets amp-escape \ help version file quiet \ - factor binary3 binary2 binary dc + factor binary3 binary2 binary dc overwrap TESTS_ENVIRONMENT = MAKE="$(MAKE)" VERSION="$(VERSION)" \ $(LOCALCHARSET_TESTS_ENVIRONMENT) @@ -77,6 +77,7 @@ EXTRA_DIST = \ numsub3.good numsub3.inp numsub3.sed \ numsub4.good numsub4.inp numsub4.sed \ numsub5.good numsub5.inp numsub5.sed \ + overwrap.good overwrap.inp overwrap.sed \ readin.good readin.inp readin.sed \ recall.good recall.inp recall.sed \ recall2.good recall2.inp recall2.sed \ diff --git a/testsuite/Makefile.tests b/testsuite/Makefile.tests index 7f50f50..80d5fe6 100644 --- a/testsuite/Makefile.tests +++ b/testsuite/Makefile.tests @@ -21,7 +21,7 @@ SKIP = :>address@hidden; exit 77 enable sep inclib 8bit 8to7 newjis xabcx dollar noeol bkslashes \ numsub head madding mac-mf empty xbxcx xbxcx3 recall recall2 xemacs \ appquit fasts uniq manis linecnt khadafy allsub flipcase space modulo \ -y-bracket y-newline y-zero insert brackets amp-escape:: +y-bracket y-newline y-zero insert brackets amp-escape overwrap:: $(SEDENV) $(SED) -f $(srcdir)/address@hidden \ < $(srcdir)/address@hidden | $(TR) -d \\r > address@hidden $(CMP) $(srcdir)/address@hidden address@hidden diff --git a/testsuite/overwrap.good b/testsuite/overwrap.good new file mode 100644 index 0000000..1174545 --- /dev/null +++ b/testsuite/overwrap.good @@ -0,0 +1,4 @@ +1 +8 +9 +10 diff --git a/testsuite/overwrap.inp b/testsuite/overwrap.inp new file mode 100644 index 0000000..f00c965 --- /dev/null +++ b/testsuite/overwrap.inp @@ -0,0 +1,10 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/testsuite/overwrap.sed b/testsuite/overwrap.sed new file mode 100644 index 0000000..b8dc882 --- /dev/null +++ b/testsuite/overwrap.sed @@ -0,0 +1 @@ +2,7d;3,6d -- 2.2.0