diff options
author | Rob Landley <rob@landley.net> | 2016-02-17 19:21:44 -0600 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2016-02-17 19:21:44 -0600 |
commit | 32b3587af261c2fb416f5de1be8f00fd5c1283d5 (patch) | |
tree | e90d46583887f3dbf614130885526a85a76e9581 | |
parent | b66a29ab58c686c98ab9683c5c544f40a1ea35f5 (diff) | |
download | toybox-32b3587af261c2fb416f5de1be8f00fd5c1283d5.tar.gz |
The perl build's attempt to escape spaces and such in LD_LIBRARY_PATH is _SAD_.
It uses a sed expression that assumes you can escape - to use it as a literal
(you can't, it has to be first or last char of the range), and assumes
you have to escape delimiters in sed [] context (you don't), and/or that
non-printf escapes become the literal character (they don't, the backslash
is preserved as a literal), meaning it winds up doing "s/[\-\]//" which is
a length 1 range, which is officially undefined behavior according to posix,
and regcomp errors out.
But if we don't accept it (like other implementations do) the perl build
breaks. So collapse [A-A] into just [A].
Testcae taken from perl 5.22.0 file Makefile.SH line 8.
(While we're at it, remove an unused argument from a function.)
-rwxr-xr-x | tests/sed.test | 6 | ||||
-rw-r--r-- | toys/posix/sed.c | 21 |
2 files changed, 18 insertions, 9 deletions
diff --git a/tests/sed.test b/tests/sed.test index eff2306a..c62f9c4d 100755 --- a/tests/sed.test +++ b/tests/sed.test @@ -131,10 +131,13 @@ hello'" "merp\nhello\n" "" "merp" testing "" "sed -e '/x/c\' -e 'y'" 'y\n' '' 'x\n' testing "" "sed -e 's/a[([]*b/X/'" 'X' '' 'a[(b' +testing "" "sed 'y/a\\bc/de\f/'" "db\f" "" "abc" +testing "sed [a-a] (for perl)" "sed '"'s/\([^a-zA-Z0-9.:_\-\/]\)/\\\1/g'"'" \ + 'he\ llo' "" "he llo" # You have to match the first line of a range in order to activate # the range, numeric and ascii work the same way -testing "skip start of range" "sed -e n -e '1,2s/b/c/'" "a\nb\n" "" "a\nb\n" +testing "sed skip start of range" "sed -e n -e '1,2s/b/c/'" "a\nb\n" "" "a\nb\n" #echo meep | sed/sed -e '1a\' -e 'huh' #echo blah | sed/sed -f <(echo -e "1a\\\\\nboom") @@ -146,4 +149,5 @@ testing "sed bonus backslashes" \ "hello\nl x\nab\nc\n" "" "hello\n" # -i with $ last line test + exit $FAILCOUNT diff --git a/toys/posix/sed.c b/toys/posix/sed.c index 013dc6b8..9b5e6664 100644 --- a/toys/posix/sed.c +++ b/toys/posix/sed.c @@ -701,7 +701,7 @@ static void do_sed(int fd, char *name) // returns processed copy of string (0 if error), *pstr advances to next // unused char. if delim (or *delim) is 0 uses/saves starting char as delimiter // if regxex, ignore delimiter in [ranges] -static char *unescape_delimited_string(char **pstr, char *delim, int regex) +static char *unescape_delimited_string(char **pstr, char *delim) { char *to, *from, mode = 0, d; @@ -720,9 +720,14 @@ static char *unescape_delimited_string(char **pstr, char *delim, int regex) // delimiter in regex character range doesn't count if (!mode && *from == '[') { mode = '['; - if (from[1] == ']') *(to++) = *(from++); + if (from[1]=='-' || from[1]==']') *(to++) = *(from++); } else if (mode && *from == ']') mode = 0; - else if (*from == '\\') { + // Length 1 range (X-X with same X) is "undefined" and makes regcomp err, + // but the perl build does it, so we need to filter it out. + else if (mode && *from == '-' && from[-1] == from[1]) { + from+=2; + continue; + } else if (*from == '\\') { if (!from[1]) return 0; // Check escaped end delimiter before printf style escapes. @@ -735,7 +740,7 @@ static char *unescape_delimited_string(char **pstr, char *delim, int regex) *(to++) = c; from+=2; continue; - } else *(to++) = *(from++); + } else if (!mode) *(to++) = *(from++); } } *(to++) = *(from++); @@ -802,7 +807,7 @@ static void jewel_of_judgement(char **pline, long len) } else if (*line == '/' || *line == '\\') { char *s = line; - if (!(s = unescape_delimited_string(&line, 0, 1))) goto brand; + if (!(s = unescape_delimited_string(&line, 0))) goto brand; if (!*s) corwin->rmatch[i] = 0; else { xregcomp((void *)reg, s, (toys.optflags & FLAG_r)*REG_EXTENDED); @@ -844,7 +849,7 @@ static void jewel_of_judgement(char **pline, long len) // get pattern (just record, we parse it later) corwin->arg2 = reg - (char *)corwin; - if (!(TT.remember = unescape_delimited_string(&line, &delim, 1))) + if (!(TT.remember = unescape_delimited_string(&line, &delim))) goto brand; reg += sizeof(regex_t); @@ -940,13 +945,13 @@ writenow: char *s, delim = 0; int len; - if (!(s = unescape_delimited_string(&line, &delim, 0))) goto brand; + if (!(s = unescape_delimited_string(&line, &delim))) goto brand; corwin->arg1 = reg-(char *)corwin; len = strlen(s); reg = extend_string((void *)&corwin, s, reg-(char *)corwin, len); free(s); corwin->arg2 = reg-(char *)corwin; - if (!(s = unescape_delimited_string(&line, &delim, 0))) goto brand; + if (!(s = unescape_delimited_string(&line, &delim))) goto brand; if (len != strlen(s)) goto brand; reg = extend_string((void *)&corwin, s, reg-(char*)corwin, len); free(s); |