correctly handle nested ADELIM parsing: ADELIM doubles as CSUBST (LP#1453827)

This commit is contained in:
tg 2016-01-14 22:30:43 +00:00
parent 000580ca8f
commit 0141794c2e
2 changed files with 21 additions and 13 deletions

11
eval.c
View File

@ -2,7 +2,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2015 * 2011, 2012, 2013, 2014, 2015, 2016
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.178 2015/12/12 22:24:07 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.179 2016/01/14 22:30:43 tg Exp $");
/* /*
* string expansion * string expansion
@ -437,8 +437,6 @@ expand(
beg = wdcopy(sp, ATEMP); beg = wdcopy(sp, ATEMP);
mid = beg + (wdscan(sp, ADELIM) - sp); mid = beg + (wdscan(sp, ADELIM) - sp);
stg = beg + (wdscan(sp, CSUBST) - sp); stg = beg + (wdscan(sp, CSUBST) - sp);
if (mid >= stg)
goto unwind_substsyn;
mid[-2] = EOS; mid[-2] = EOS;
if (mid[-1] == /*{*/'}') { if (mid[-1] == /*{*/'}') {
sp += mid - beg - 1; sp += mid - beg - 1;
@ -446,9 +444,8 @@ expand(
} else { } else {
end = mid + end = mid +
(wdscan(mid, ADELIM) - mid); (wdscan(mid, ADELIM) - mid);
if (end >= stg || if (end[-1] != /*{*/ '}')
/* more than max delimiters */ /* more than max delimiters */
end[-1] != /*{*/ '}')
goto unwind_substsyn; goto unwind_substsyn;
end[-2] = EOS; end[-2] = EOS;
sp += end - beg - 1; sp += end - beg - 1;
@ -488,8 +485,6 @@ expand(
s = wdcopy(sp, ATEMP); s = wdcopy(sp, ATEMP);
p = s + (wdscan(sp, ADELIM) - sp); p = s + (wdscan(sp, ADELIM) - sp);
d = s + (wdscan(sp, CSUBST) - sp); d = s + (wdscan(sp, CSUBST) - sp);
if (p >= d)
goto unwind_substsyn;
p[-2] = EOS; p[-2] = EOS;
if (p[-1] == /*{*/'}') if (p[-1] == /*{*/'}')
d = NULL; d = NULL;

21
tree.c
View File

@ -2,7 +2,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2015 * 2011, 2012, 2013, 2015, 2016
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.79 2015/12/12 19:08:58 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.80 2016/01/14 22:30:43 tg Exp $");
#define INDENT 8 #define INDENT 8
@ -318,6 +318,10 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
case EOS: case EOS:
return (--wp); return (--wp);
case ADELIM: case ADELIM:
if (*wp == /*{*/'}') {
++wp;
goto wdvarput_csubst;
}
case CHAR: case CHAR:
c = *wp++; c = *wp++;
shf_putc(c, shf); shf_putc(c, shf);
@ -383,8 +387,10 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
wp = wdvarput(shf, wp, 0, opmode); wp = wdvarput(shf, wp, 0, opmode);
break; break;
case CSUBST: case CSUBST:
if (*wp++ == '}') if (*wp++ == '}') {
wdvarput_csubst:
shf_putc('}', shf); shf_putc('}', shf);
}
return (wp); return (wp);
case OPAT: case OPAT:
shf_putchar(*wp++, shf); shf_putchar(*wp++, shf);
@ -581,8 +587,10 @@ wdscan(const char *wp, int c)
case EOS: case EOS:
return (wp); return (wp);
case ADELIM: case ADELIM:
if (c == ADELIM) if (c == ADELIM && nest == 0)
return (wp + 1); return (wp + 1);
if (*wp == /*{*/'}')
goto wdscan_csubst;
/* FALLTHROUGH */ /* FALLTHROUGH */
case CHAR: case CHAR:
case QCHAR: case QCHAR:
@ -604,6 +612,7 @@ wdscan(const char *wp, int c)
; ;
break; break;
case CSUBST: case CSUBST:
wdscan_csubst:
wp++; wp++;
if (c == CSUBST && nest == 0) if (c == CSUBST && nest == 0)
return (wp); return (wp);
@ -807,6 +816,10 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
shf_puts("EOS", shf); shf_puts("EOS", shf);
return (--wp); return (--wp);
case ADELIM: case ADELIM:
if (*wp == /*{*/'}') {
shf_puts("]ADELIM(})", shf);
return (wp + 1);
}
shf_puts("ADELIM=", shf); shf_puts("ADELIM=", shf);
if (0) if (0)
case CHAR: case CHAR: