diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-17 01:35:04 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-17 01:35:04 +0200 |
| commit | f210cff601cf034c522b41cae6acd4f56060126d (patch) | |
| tree | 5d65de6fa4eccdb44448cef2baf9efb65b4ab40e | |
| parent | 16d1e3c26fc2908d430aa94cc76227028b0fffc7 (diff) | |
| download | busybox-w32-f210cff601cf034c522b41cae6acd4f56060126d.tar.gz busybox-w32-f210cff601cf034c522b41cae6acd4f56060126d.tar.bz2 busybox-w32-f210cff601cf034c522b41cae6acd4f56060126d.zip | |
sed: fix " echo /usr/lib | sed 's,\(^/\|\)[^/][^/]*,..,g' " bug
function old new delta
process_files 2102 2091 -11
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | editors/sed.c | 45 | ||||
| -rwxr-xr-x | testsuite/sed.tests | 7 |
2 files changed, 33 insertions, 19 deletions
diff --git a/editors/sed.c b/editors/sed.c index de18996b8..8b4f60a8c 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
| @@ -589,7 +589,7 @@ static void pipe_putc(char c) | |||
| 589 | 589 | ||
| 590 | static void do_subst_w_backrefs(char *line, char *replace) | 590 | static void do_subst_w_backrefs(char *line, char *replace) |
| 591 | { | 591 | { |
| 592 | int i,j; | 592 | int i, j; |
| 593 | 593 | ||
| 594 | /* go through the replacement string */ | 594 | /* go through the replacement string */ |
| 595 | for (i = 0; replace[i]; i++) { | 595 | for (i = 0; replace[i]; i++) { |
| @@ -624,23 +624,24 @@ static void do_subst_w_backrefs(char *line, char *replace) | |||
| 624 | } | 624 | } |
| 625 | } | 625 | } |
| 626 | 626 | ||
| 627 | static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | 627 | static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p) |
| 628 | { | 628 | { |
| 629 | char *oldline = *line; | 629 | char *line = *line_p; |
| 630 | int altered = 0; | 630 | int altered = 0; |
| 631 | unsigned match_count = 0; | 631 | unsigned match_count = 0; |
| 632 | regex_t *current_regex; | 632 | regex_t *current_regex; |
| 633 | 633 | ||
| 634 | current_regex = sed_cmd->sub_match; | ||
| 634 | /* Handle empty regex. */ | 635 | /* Handle empty regex. */ |
| 635 | if (sed_cmd->sub_match == NULL) { | 636 | if (!current_regex) { |
| 636 | current_regex = G.previous_regex_ptr; | 637 | current_regex = G.previous_regex_ptr; |
| 637 | if (!current_regex) | 638 | if (!current_regex) |
| 638 | bb_error_msg_and_die("no previous regexp"); | 639 | bb_error_msg_and_die("no previous regexp"); |
| 639 | } else | 640 | } |
| 640 | G.previous_regex_ptr = current_regex = sed_cmd->sub_match; | 641 | G.previous_regex_ptr = current_regex; |
| 641 | 642 | ||
| 642 | /* Find the first match */ | 643 | /* Find the first match */ |
| 643 | if (REG_NOMATCH == regexec(current_regex, oldline, 10, G.regmatch, 0)) | 644 | if (REG_NOMATCH == regexec(current_regex, line, 10, G.regmatch, 0)) |
| 644 | return 0; | 645 | return 0; |
| 645 | 646 | ||
| 646 | /* Initialize temporary output buffer. */ | 647 | /* Initialize temporary output buffer. */ |
| @@ -657,7 +658,7 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
| 657 | The match_count check is so not to break | 658 | The match_count check is so not to break |
| 658 | echo "hi" | busybox sed 's/^/!/g' */ | 659 | echo "hi" | busybox sed 's/^/!/g' */ |
| 659 | if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) { | 660 | if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) { |
| 660 | pipe_putc(*oldline++); | 661 | pipe_putc(*line++); |
| 661 | continue; | 662 | continue; |
| 662 | } | 663 | } |
| 663 | 664 | ||
| @@ -669,35 +670,41 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
| 669 | && (sed_cmd->which_match != match_count) | 670 | && (sed_cmd->which_match != match_count) |
| 670 | ) { | 671 | ) { |
| 671 | for (i = 0; i < G.regmatch[0].rm_eo; i++) | 672 | for (i = 0; i < G.regmatch[0].rm_eo; i++) |
| 672 | pipe_putc(*oldline++); | 673 | pipe_putc(*line++); |
| 673 | continue; | 674 | continue; |
| 674 | } | 675 | } |
| 675 | 676 | ||
| 676 | /* print everything before the match */ | 677 | /* print everything before the match */ |
| 677 | for (i = 0; i < G.regmatch[0].rm_so; i++) | 678 | for (i = 0; i < G.regmatch[0].rm_so; i++) |
| 678 | pipe_putc(oldline[i]); | 679 | pipe_putc(line[i]); |
| 679 | 680 | ||
| 680 | /* then print the substitution string */ | 681 | /* then print the substitution string */ |
| 681 | do_subst_w_backrefs(oldline, sed_cmd->string); | 682 | do_subst_w_backrefs(line, sed_cmd->string); |
| 682 | 683 | ||
| 683 | /* advance past the match */ | 684 | /* advance past the match */ |
| 684 | oldline += G.regmatch[0].rm_eo; | 685 | line += G.regmatch[0].rm_eo; |
| 685 | /* flag that something has changed */ | 686 | /* flag that something has changed */ |
| 686 | altered++; | 687 | altered++; |
| 687 | 688 | ||
| 688 | /* if we're not doing this globally, get out now */ | 689 | /* if we're not doing this globally, get out now */ |
| 689 | if (sed_cmd->which_match) | 690 | if (sed_cmd->which_match) |
| 690 | break; | 691 | break; |
| 691 | } while (*oldline && (regexec(current_regex, oldline, 10, G.regmatch, 0) != REG_NOMATCH)); | ||
| 692 | 692 | ||
| 693 | /* Copy rest of string into output pipeline */ | 693 | if (*line == '\0') |
| 694 | break; | ||
| 695 | //maybe (G.regmatch[0].rm_eo ? REG_NOTBOL : 0) instead of unconditional REG_NOTBOL? | ||
| 696 | } while (regexec(current_regex, line, 10, G.regmatch, REG_NOTBOL) != REG_NOMATCH); | ||
| 694 | 697 | ||
| 695 | while (*oldline) | 698 | /* Copy rest of string into output pipeline */ |
| 696 | pipe_putc(*oldline++); | 699 | while (1) { |
| 697 | pipe_putc(0); | 700 | char c = *line++; |
| 701 | pipe_putc(c); | ||
| 702 | if (c == '\0') | ||
| 703 | break; | ||
| 704 | } | ||
| 698 | 705 | ||
| 699 | free(*line); | 706 | free(*line_p); |
| 700 | *line = G.pipeline.buf; | 707 | *line_p = G.pipeline.buf; |
| 701 | return altered; | 708 | return altered; |
| 702 | } | 709 | } |
| 703 | 710 | ||
diff --git a/testsuite/sed.tests b/testsuite/sed.tests index a9d9ada31..696d980ef 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests | |||
| @@ -241,4 +241,11 @@ testing "sed 2d;2,1p (gnu compat)" \ | |||
| 241 | "third\n" "" \ | 241 | "third\n" "" \ |
| 242 | "first\nsecond\nthird\nfourth\n" | 242 | "first\nsecond\nthird\nfourth\n" |
| 243 | 243 | ||
| 244 | # Regex means: "match / at BOL or nothing, then one or more not-slashes". | ||
| 245 | # The bug was that second slash in /usr/lib was treated as "at BOL" too. | ||
| 246 | testing "sed beginning (^) matches only once" \ | ||
| 247 | "sed 's,\(^/\|\)[^/][^/]*,>\0<,g'" \ | ||
| 248 | ">/usr</>lib<\n" "" \ | ||
| 249 | "/usr/lib\n" | ||
| 250 | |||
| 244 | exit $FAILCOUNT | 251 | exit $FAILCOUNT |
