From: Peter Avalos Date: Sun, 7 Jan 2007 16:58:30 +0000 (+0000) Subject: Fix expanding of quoted positional parameters in case patterns. X-Git-Tag: v2.0.1~3801 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/af260b21ae04ae25800cb5d92cc02f2298706851 Fix expanding of quoted positional parameters in case patterns. When parsing an invalid parameter expansion (eg. ${} or ${foo@bar}) do not issue a syntax error immediately but save the information that it is erroneous for later when the parameter expansion is actually done. This means eg. "false && ${}" will not generate an error which seems to be required by POSIX. Remove some white space at EOL. The sub-expression "(nulonly || 1)" always evaluates to true and according to CVS logs seems to be just a left-over from some debugging and introduced by accident. Remove collate_range_cmp() stabilization, it conflicts with ranges Replace various spellings with FALLTHROUGH which is lint()able Obtained-from: FreeBSD --- diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 79ee2125fa..8172c27d7f 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -34,8 +34,8 @@ * SUCH DAMAGE. * * @(#)expand.c 8.5 (Berkeley) 5/15/95 - * $FreeBSD: src/bin/sh/expand.c,v 1.31.2.5 2003/01/17 07:44:01 tjr Exp $ - * $DragonFly: src/bin/sh/expand.c,v 1.8 2007/01/07 08:26:55 pavalos Exp $ + * $FreeBSD: src/bin/sh/expand.c,v 1.51 2006/11/07 22:46:13 stefanf Exp $ + * $DragonFly: src/bin/sh/expand.c,v 1.9 2007/01/07 16:58:30 pavalos Exp $ */ #include @@ -98,9 +98,9 @@ STATIC void expbackq(union node *, int, int); STATIC int subevalvar(char *, char *, int, int, int, int); STATIC char *evalvar(char *, int); STATIC int varisset(char *, int); -STATIC void varvalue(char *, int, int); +STATIC void varvalue(char *, int, int, int); STATIC void recordregion(int, int, int); -STATIC void removerecordregions(int); +STATIC void removerecordregions(int); STATIC void ifsbreakup(char *, struct arglist *); STATIC void expandmeta(struct strlist *, int); STATIC void expmeta(char *, char *); @@ -112,20 +112,13 @@ STATIC char *cvtnum(int, char *); STATIC int collate_range_cmp(int, int); STATIC int -collate_range_cmp (int c1, int c2) +collate_range_cmp(int c1, int c2) { static char s1[2], s2[2]; - int ret; - c1 &= UCHAR_MAX; - c2 &= UCHAR_MAX; - if (c1 == c2) - return (0); s1[0] = c1; s2[0] = c2; - if ((ret = strcoll(s1, s2)) != 0) - return (ret); - return (c1 - c2); + return (strcoll(s1, s2)); } extern int oexitstatus; @@ -318,7 +311,7 @@ lose: } -STATIC void +STATIC void removerecordregions(int endoff) { if (ifslastp == NULL) @@ -341,7 +334,7 @@ removerecordregions(int endoff) } return; } - + ifslastp = &ifsfirst; while (ifslastp->next && ifslastp->next->begoff < endoff) ifslastp=ifslastp->next; @@ -529,7 +522,7 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc, outfmt(&errout, "%s\n", startp); error((char *)NULL); } - error("%.*s: parameter %snot set", p - str - 1, + error("%.*s: parameter %snot set", (int)(p - str - 1), str, (varflags & VSNUL) ? "null or " : nullstr); return 0; @@ -578,7 +571,7 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc, } loc--; if ((varflags & VSQUOTE) && loc > startp && - *(loc - 1) == CTLESC) { + *(loc - 1) == CTLESC) { for (q = startp; q < loc; q++) if (*q == CTLESC) q++; @@ -635,7 +628,7 @@ evalvar(char *p, int flag) int easy; int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); - varflags = *p++; + varflags = (unsigned char)*p++; subtype = varflags & VSTYPE; var = p; special = 0; @@ -664,13 +657,14 @@ again: /* jump here after setting a variable with ${var=text} */ case VSTRIMRIGHT: case VSTRIMRIGHTMAX: case VSLENGTH: - error("%.*s: parameter not set", p - var - 1, var); + error("%.*s: parameter not set", (int)(p - var - 1), + var); } } if (set && subtype != VSPLUS) { /* insert the value of the variable */ if (special) { - varvalue(var, varflags & VSQUOTE, flag & EXP_FULL); + varvalue(var, varflags & VSQUOTE, subtype, flag); if (subtype == VSLENGTH) { varlen = expdest - stackblock() - startloc; STADJUST(-varlen, expdest); @@ -751,9 +745,9 @@ record: if (!set) { if (subevalvar(p, var, 0, subtype, startloc, varflags)) { varflags &= ~VSNUL; - /* - * Remove any recorded regions beyond - * start of variable + /* + * Remove any recorded regions beyond + * start of variable */ removerecordregions(startloc); goto again; @@ -764,6 +758,11 @@ record: goto record; break; + case VSERROR: + c = p - var - 1; + error("${%.*s%s}: Bad substitution", c, var, + (c > 0 && *p != CTLENDVAR) ? "..." : ""); + default: abort(); } @@ -837,7 +836,7 @@ varisset(char *name, int nulok) */ STATIC void -varvalue(char *name, int quoted, int allow_split) +varvalue(char *name, int quoted, int subtype, int flag) { int num; char *p; @@ -848,7 +847,7 @@ varvalue(char *name, int quoted, int allow_split) #define STRTODEST(p) \ do {\ - if (allow_split) { \ + if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \ syntax = quoted? DQSYNTAX : BASESYNTAX; \ while (*p) { \ if (syntax[(int)*p] == CCTL) \ @@ -883,7 +882,7 @@ numvar: } break; case '@': - if (allow_split && quoted) { + if (flag & EXP_FULL && quoted) { for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { STRTODEST(p); if (*ap) @@ -891,9 +890,9 @@ numvar: } break; } - /* fall through */ + /* FALLTHROUGH */ case '*': - if (ifsset() != 0) + if (ifsset()) sep = ifsval()[0]; else sep = ' '; @@ -972,7 +971,7 @@ ifsbreakup(char *string, struct arglist *arglist) do { p = string + ifsp->begoff; nulonly = ifsp->nulonly; - ifs = nulonly ? nullstr : + ifs = nulonly ? nullstr : ( ifsset() ? ifsval() : " \t\n" ); ifsspc = 0; while (p < string + ifsp->endoff) { @@ -1022,8 +1021,7 @@ ifsbreakup(char *string, struct arglist *arglist) p++; } } while ((ifsp = ifsp->next) != NULL); - if (*start || (!ifsspc && start > string && - (nulonly || 1))) { + if (*start || (!ifsspc && start > string)) { sp = (struct strlist *)stalloc(sizeof *sp); sp->text = start; *arglist->lastp = sp; diff --git a/bin/sh/parser.c b/bin/sh/parser.c index fb0a51e9ec..9f7471196e 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -35,7 +35,7 @@ * * @(#)parser.c 8.7 (Berkeley) 5/16/95 * $FreeBSD: src/bin/sh/parser.c,v 1.29.2.9 2002/10/18 11:24:04 tjr Exp $ - * $DragonFly: src/bin/sh/parser.c,v 1.8 2006/09/28 22:29:44 pavalos Exp $ + * $DragonFly: src/bin/sh/parser.c,v 1.9 2007/01/07 16:58:30 pavalos Exp $ */ #include @@ -1221,12 +1221,17 @@ parsesub: { c = pgetc(); } } else { - if (! is_special(c)) -badsub: synerror("Bad substitution"); - USTPUTC(c, out); - c = pgetc(); + if (! is_special(c)) { + subtype = VSERROR; + if (c == '}') + pungetc(); + else + USTPUTC(c, out); + } else { + USTPUTC(c, out); + c = pgetc(); + } } - STPUTC('=', out); flags = 0; if (subtype == 0) { switch (c) { @@ -1236,9 +1241,13 @@ badsub: synerror("Bad substitution"); /*FALLTHROUGH*/ default: p = strchr(types, c); - if (p == NULL) - goto badsub; - subtype = p - types + VSNORMAL; + if (p == NULL) { + if (flags == VSNUL) + STPUTC(':', out); + STPUTC(c, out); + subtype = VSERROR; + } else + subtype = p - types + VSNORMAL; break; case '%': case '#': @@ -1254,9 +1263,10 @@ badsub: synerror("Bad substitution"); break; } } - } else { + } else if (subtype != VSERROR) { pungetc(); } + STPUTC('=', out); if (subtype != VSLENGTH && (dblquote || arinest)) flags |= VSQUOTE; *(stackblock() + typeloc) = subtype | flags; diff --git a/bin/sh/parser.h b/bin/sh/parser.h index c493708174..877bf1daa1 100644 --- a/bin/sh/parser.h +++ b/bin/sh/parser.h @@ -34,8 +34,8 @@ * SUCH DAMAGE. * * @(#)parser.h 8.3 (Berkeley) 5/4/95 - * $FreeBSD: src/bin/sh/parser.h,v 1.8.2.1 2002/07/19 04:38:52 tjr Exp $ - * $DragonFly: src/bin/sh/parser.h,v 1.3 2004/03/19 18:39:41 cpressey Exp $ + * $FreeBSD: src/bin/sh/parser.h,v 1.11 2006/11/05 18:36:05 stefanf Exp $ + * $DragonFly: src/bin/sh/parser.h,v 1.4 2007/01/07 16:58:30 pavalos Exp $ */ /* control characters in argument strings */ @@ -65,6 +65,7 @@ #define VSTRIMRIGHT 0x8 /* ${var%pattern} */ #define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */ #define VSLENGTH 0xa /* ${#var} */ +#define VSERROR 0xb /* Syntax error, issue when expanded */ /*