From 32b3587af261c2fb416f5de1be8f00fd5c1283d5 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 17 Feb 2016 19:21:44 -0600 Subject: 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.) --- toys/posix/sed.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'toys/posix/sed.c') 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); -- cgit v1.2.3