From 0fcc6c8fb28f4cc61520770da2156de3a124e432 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 6 Nov 2015 17:28:02 +0000 Subject: 37073: another SH_WORD_SPLIT problem. In cases like x${:- y} the space was simply removed instead of being used for splitting. --- Src/subst.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'Src') diff --git a/Src/subst.c b/Src/subst.c index 021d23444..528912134 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -430,11 +430,16 @@ singsub(char **s) * set to 1. Otherwise, *isarr is set to 0, and the result is put into *s, * with any necessary joining of multiple elements using sep (which can be * NULL to use IFS). The return value is true iff the expansion resulted - * in an empty list. */ + * in an empty list. + * + * *ws_at_start is set to 1 if the string had whitespace at thes start + * that should cause word splitting against any preceeding string. + */ /**/ static int -multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep) +multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, + int *ws_at_start) { int l; char **r, **p, *x = *s; @@ -450,6 +455,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep) l++; if (!iwsep(STOUC(c))) break; + *ws_at_start = 1; } } @@ -1717,6 +1723,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * This is for compatibility. */ int horrible_offset_hack = 0; + /* + * Signal back from multsub: with something like + * x${:- $foo} + * with word-splitting active we need to split on that leading + * whitespace. However, if there's no "x" the whitespace is + * simply removed. + */ + int ws_at_start = 0; *s++ = '\0'; /* @@ -2265,7 +2279,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * remove the aspar test and extract a value from an array, if * necessary, when we handle (P) lower down. */ - if (multsub(&val, 0, (aspar ? NULL : &aval), &isarr, NULL) && quoted) { + if (multsub(&val, 0, (aspar ? NULL : &aval), &isarr, NULL, + &ws_at_start) && quoted) { /* Empty quoted string --- treat as null string, not elided */ isarr = -1; aval = (char **) hcalloc(sizeof(char *)); @@ -2736,7 +2751,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) split_flags = PREFORK_NOSHWORDSPLIT; } multsub(&val, split_flags, (aspar ? NULL : &aval), - &isarr, NULL); + &isarr, NULL, &ws_at_start); copied = 1; spbreak = 0; /* Leave globsubst on if forced */ @@ -2765,13 +2780,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * behavior on caller choice of PREFORK_SHWORDSPLIT. */ multsub(&val, spbreak ? PREFORK_SINGLE : PREFORK_NOSHWORDSPLIT, - NULL, &isarr, NULL); + NULL, &isarr, NULL, &ws_at_start); } else { if (spbreak) split_flags = PREFORK_SPLIT|PREFORK_SHWORDSPLIT; else split_flags = PREFORK_NOSHWORDSPLIT; - multsub(&val, split_flags, &aval, &isarr, NULL); + multsub(&val, split_flags, &aval, &isarr, NULL, + &ws_at_start); spbreak = 0; } if (arrasg) { @@ -3303,6 +3319,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) } if (haserr || errflag) return NULL; + ws_at_start = 0; } /* * This handles taking a length with ${#foo} and variations. @@ -3341,6 +3358,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) sprintf(buf, "%ld", len); val = dupstring(buf); isarr = 0; + ws_at_start = 0; } /* At this point we make sure that our arrayness has affected the * arrayness of the linked list. Then, we can turn our value into @@ -3370,6 +3388,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) if (isarr) { val = sepjoin(aval, sep, 1); isarr = 0; + ws_at_start = 0; } if (!ssub && (spbreak || spsep)) { aval = sepsplit(val, spsep, 0, 1); @@ -3649,6 +3668,15 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * equivalent and only locally decide if we need to treat it * as a scalar.) */ + + /* + * If a multsub result had whitespace at the start and we're + * splitting and there's a previous string, now's the time to do so. + */ + if (ws_at_start && aptr > ostr) { + insertlinknode(l, n, dupstrpfx(ostr, aptr - ostr)), incnode(n); + ostr = aptr; + } if (isarr) { char *x; char *y; -- cgit 1.4.1