From 60f7eec450c6174dafb47ccd96b247293dbc75c9 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 29 Oct 2010 19:34:57 +0000 Subject: [PATCH] sh: Fix some issues with CTL* bytes and ${var#pat}. subevalvar() incorrectly assumed that CTLESC bytes were present iff the expansion was quoted. However, they are present iff various processing such as word splitting is to be done later on. Example: v=@$e@$e@$e@ y="${v##*"$e"}" echo "$y" failed if $e contained the magic CTLESC byte. Exp-run done by: pav (with some other sh(1) changes) --- bin/sh/expand.c | 27 +++++++++++------------ tools/regression/bin/sh/expansion/trim6.0 | 22 ++++++++++++++++++ 2 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 tools/regression/bin/sh/expansion/trim6.0 diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 13dc38a9a16b..200da3f046d4 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -98,7 +98,7 @@ static struct arglist exparg; /* holds expanded arg list */ static void argstr(char *, int); static char *exptilde(char *, int); static void expbackq(union node *, int, int); -static int subevalvar(char *, char *, int, int, int, int); +static int subevalvar(char *, char *, int, int, int, int, int); static char *evalvar(char *, int); static int varisset(char *, int); static void varvalue(char *, int, int, int); @@ -526,7 +526,7 @@ expbackq(union node *cmd, int quoted, int flag) static int subevalvar(char *p, char *str, int strloc, int subtype, int startloc, - int varflags) + int varflags, int quotes) { char *startp; char *loc = NULL; @@ -571,12 +571,12 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc, for (loc = startp; loc < str; loc++) { c = *loc; *loc = '\0'; - if (patmatch(str, startp, varflags & VSQUOTE)) { + if (patmatch(str, startp, quotes)) { *loc = c; goto recordleft; } *loc = c; - if ((varflags & VSQUOTE) && *loc == CTLESC) + if (quotes && *loc == CTLESC) loc++; } return 0; @@ -585,14 +585,13 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc, for (loc = str - 1; loc >= startp;) { c = *loc; *loc = '\0'; - if (patmatch(str, startp, varflags & VSQUOTE)) { + if (patmatch(str, startp, quotes)) { *loc = c; goto recordleft; } *loc = c; loc--; - if ((varflags & VSQUOTE) && loc > startp && - *(loc - 1) == CTLESC) { + if (quotes && loc > startp && *(loc - 1) == CTLESC) { for (q = startp; q < loc; q++) if (*q == CTLESC) q++; @@ -604,14 +603,13 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc, case VSTRIMRIGHT: for (loc = str - 1; loc >= startp;) { - if (patmatch(str, loc, varflags & VSQUOTE)) { + if (patmatch(str, loc, quotes)) { amount = loc - expdest; STADJUST(amount, expdest); return 1; } loc--; - if ((varflags & VSQUOTE) && loc > startp && - *(loc - 1) == CTLESC) { + if (quotes && loc > startp && *(loc - 1) == CTLESC) { for (q = startp; q < loc; q++) if (*q == CTLESC) q++; @@ -623,12 +621,12 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc, case VSTRIMRIGHTMAX: for (loc = startp; loc < str - 1; loc++) { - if (patmatch(str, loc, varflags & VSQUOTE)) { + if (patmatch(str, loc, quotes)) { amount = loc - expdest; STADJUST(amount, expdest); return 1; } - if ((varflags & VSQUOTE) && *loc == CTLESC) + if (quotes && *loc == CTLESC) loc++; } return 0; @@ -779,7 +777,7 @@ evalvar(char *p, int flag) STPUTC('\0', expdest); patloc = expdest - stackblock(); if (subevalvar(p, NULL, patloc, subtype, - startloc, varflags) == 0) { + startloc, varflags, quotes) == 0) { int amount = (expdest - stackblock() - patloc) + 1; STADJUST(-amount, expdest); } @@ -790,7 +788,8 @@ evalvar(char *p, int flag) case VSASSIGN: case VSQUESTION: if (!set) { - if (subevalvar(p, var, 0, subtype, startloc, varflags)) { + if (subevalvar(p, var, 0, subtype, startloc, varflags, + quotes)) { varflags &= ~VSNUL; /* * Remove any recorded regions beyond diff --git a/tools/regression/bin/sh/expansion/trim6.0 b/tools/regression/bin/sh/expansion/trim6.0 new file mode 100644 index 000000000000..3f753c4113f6 --- /dev/null +++ b/tools/regression/bin/sh/expansion/trim6.0 @@ -0,0 +1,22 @@ +# $FreeBSD$ + +e= +for i in 0 1 2 3; do + for j in 0 1 2 3 4 5 6 7; do + for k in 0 1 2 3 4 5 6 7; do + case $i$j$k in + 000) continue ;; + esac + e="$e\\$i$j$k" + done + done +done +e=$(printf "$e") +v=@$e@$e@ +y=${v##*"$e"} +yq="${v##*"$e"}" +[ "$y" = @ ] || echo "error when unquoted in non-splitting context" +[ "$yq" = @ ] || echo "error when quoted in non-splitting context" +[ "${v##*"$e"}" = @ ] || echo "error when quoted in splitting context" +IFS= +[ ${v##*"$e"} = @ ] || echo "error when unquoted in splitting context"