1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
diff -d -urpN busybox.2/editors/sed.c busybox.3/editors/sed.c
--- busybox.2/editors/sed.c 2009-08-08 01:40:42.000000000 +0200
+++ busybox.3/editors/sed.c 2009-08-17 01:32:00.000000000 +0200
@@ -589,7 +589,7 @@ static void pipe_putc(char c)
static void do_subst_w_backrefs(char *line, char *replace)
{
- int i,j;
+ int i, j;
/* go through the replacement string */
for (i = 0; replace[i]; i++) {
@@ -624,23 +624,24 @@ static void do_subst_w_backrefs(char *li
}
}
-static int do_subst_command(sed_cmd_t *sed_cmd, char **line)
+static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p)
{
- char *oldline = *line;
+ char *line = *line_p;
int altered = 0;
unsigned match_count = 0;
regex_t *current_regex;
+ current_regex = sed_cmd->sub_match;
/* Handle empty regex. */
- if (sed_cmd->sub_match == NULL) {
+ if (!current_regex) {
current_regex = G.previous_regex_ptr;
if (!current_regex)
bb_error_msg_and_die("no previous regexp");
- } else
- G.previous_regex_ptr = current_regex = sed_cmd->sub_match;
+ }
+ G.previous_regex_ptr = current_regex;
/* Find the first match */
- if (REG_NOMATCH == regexec(current_regex, oldline, 10, G.regmatch, 0))
+ if (REG_NOMATCH == regexec(current_regex, line, 10, G.regmatch, 0))
return 0;
/* Initialize temporary output buffer. */
@@ -657,7 +658,7 @@ static int do_subst_command(sed_cmd_t *s
The match_count check is so not to break
echo "hi" | busybox sed 's/^/!/g' */
if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) {
- pipe_putc(*oldline++);
+ pipe_putc(*line++);
continue;
}
@@ -669,35 +670,41 @@ static int do_subst_command(sed_cmd_t *s
&& (sed_cmd->which_match != match_count)
) {
for (i = 0; i < G.regmatch[0].rm_eo; i++)
- pipe_putc(*oldline++);
+ pipe_putc(*line++);
continue;
}
/* print everything before the match */
for (i = 0; i < G.regmatch[0].rm_so; i++)
- pipe_putc(oldline[i]);
+ pipe_putc(line[i]);
/* then print the substitution string */
- do_subst_w_backrefs(oldline, sed_cmd->string);
+ do_subst_w_backrefs(line, sed_cmd->string);
/* advance past the match */
- oldline += G.regmatch[0].rm_eo;
+ line += G.regmatch[0].rm_eo;
/* flag that something has changed */
altered++;
/* if we're not doing this globally, get out now */
if (sed_cmd->which_match)
break;
- } while (*oldline && (regexec(current_regex, oldline, 10, G.regmatch, 0) != REG_NOMATCH));
- /* Copy rest of string into output pipeline */
+ if (*line == '\0')
+ break;
+//maybe (G.regmatch[0].rm_eo ? REG_NOTBOL : 0) instead of unconditional REG_NOTBOL?
+ } while (regexec(current_regex, line, 10, G.regmatch, REG_NOTBOL) != REG_NOMATCH);
- while (*oldline)
- pipe_putc(*oldline++);
- pipe_putc(0);
+ /* Copy rest of string into output pipeline */
+ while (1) {
+ char c = *line++;
+ pipe_putc(c);
+ if (c == '\0')
+ break;
+ }
- free(*line);
- *line = G.pipeline.buf;
+ free(*line_p);
+ *line_p = G.pipeline.buf;
return altered;
}
diff -d -urpN busybox.2/testsuite/sed.tests busybox.3/testsuite/sed.tests
--- busybox.2/testsuite/sed.tests 2009-08-08 01:40:44.000000000 +0200
+++ busybox.3/testsuite/sed.tests 2009-08-17 01:29:01.000000000 +0200
@@ -241,4 +241,11 @@ testing "sed 2d;2,1p (gnu compat)" \
"third\n" "" \
"first\nsecond\nthird\nfourth\n"
+# Regex means: "match / at BOL or nothing, then one or more not-slashes".
+# The bug was that second slash in /usr/lib was treated as "at BOL" too.
+testing "sed beginning (^) matches only once" \
+ "sed 's,\(^/\|\)[^/][^/]*,>\0<,g'" \
+ ">/usr</>lib<\n" "" \
+ "/usr/lib\n"
+
exit $FAILCOUNT
|