aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-09-29 17:17:04 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-09-29 17:17:04 +0200
commit73c3e074df4de03ba1bebce09c130c8950ea5fe4 (patch)
tree68b486c969165596a922184a0dcdd59c53438589
parent8286513838beaf9ccaab15bb5905248c3b7b8a69 (diff)
downloadbusybox-w32-73c3e074df4de03ba1bebce09c130c8950ea5fe4.tar.gz
busybox-w32-73c3e074df4de03ba1bebce09c130c8950ea5fe4.tar.bz2
busybox-w32-73c3e074df4de03ba1bebce09c130c8950ea5fe4.zip
ash: [PARSER] Handle backslash newlines properly after dollar sign
Fixes var_unbackslash1.tests failure. Upstream commit: [PARSER] Handle backslash newlines properly after dollar sign On Tue, Aug 26, 2014 at 12:34:42PM +0000, Eric Blake wrote: > On 08/26/2014 06:15 AM, Oleg Bulatov wrote: > > While playing with sh generators I found that dash and bash have different > > interpretations for <slash><newline> sequence. > > > > $ dash -c 'EDIT=xxx; echo $EDIT\ > >> OR' > > xxxOR > > Buggy. > > > > $ dash -c 'echo "$\ > > (pwd)"' > > $(pwd) > > > > Is it undefined behaviour in POSIX? > > No, it's well-defined, and dash is buggy. ... I agree. This patch should resolve this problem and similar ones affecting blackslash newlines after we encounter a dollar sign. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/shell/ash.c b/shell/ash.c
index a63d40d7e..b71fc0299 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9774,11 +9774,6 @@ popstring(void)
9774 INT_ON; 9774 INT_ON;
9775} 9775}
9776 9776
9777//FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9778//it peeks whether it is &>, and then pushes back both chars.
9779//This function needs to save last *next_to_pgetc to buf[0]
9780//to make two pungetc() reliable. Currently,
9781// pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9782static int 9777static int
9783preadfd(void) 9778preadfd(void)
9784{ 9779{
@@ -10037,6 +10032,25 @@ pungetc(void)
10037 g_parsefile->unget++; 10032 g_parsefile->unget++;
10038} 10033}
10039 10034
10035/* This one eats backslash+newline */
10036static int
10037pgetc_eatbnl(void)
10038{
10039 int c;
10040
10041 while ((c = pgetc()) == '\\') {
10042 if (pgetc() != '\n') {
10043 pungetc();
10044 break;
10045 }
10046
10047 g_parsefile->linno++;
10048 setprompt_if(doprompt, 2);
10049 }
10050
10051 return c;
10052}
10053
10040/* 10054/*
10041 * To handle the "." command, a stack of input files is used. Pushfile 10055 * To handle the "." command, a stack of input files is used. Pushfile
10042 * adds a new entry to the stack and popfile restores the previous level. 10056 * adds a new entry to the stack and popfile restores the previous level.
@@ -11625,7 +11639,7 @@ parsesub: {
11625 int typeloc; 11639 int typeloc;
11626 int flags; 11640 int flags;
11627 11641
11628 c = pgetc(); 11642 c = pgetc_eatbnl();
11629 if (c > 255 /* PEOA or PEOF */ 11643 if (c > 255 /* PEOA or PEOF */
11630 || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) 11644 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11631 ) { 11645 ) {
@@ -11638,7 +11652,7 @@ parsesub: {
11638 pungetc(); 11652 pungetc();
11639 } else if (c == '(') { 11653 } else if (c == '(') {
11640 /* $(command) or $((arith)) */ 11654 /* $(command) or $((arith)) */
11641 if (pgetc() == '(') { 11655 if (pgetc_eatbnl() == '(') {
11642#if ENABLE_SH_MATH_SUPPORT 11656#if ENABLE_SH_MATH_SUPPORT
11643 PARSEARITH(); 11657 PARSEARITH();
11644#else 11658#else
@@ -11655,9 +11669,9 @@ parsesub: {
11655 USTPUTC(VSNORMAL, out); 11669 USTPUTC(VSNORMAL, out);
11656 subtype = VSNORMAL; 11670 subtype = VSNORMAL;
11657 if (c == '{') { 11671 if (c == '{') {
11658 c = pgetc(); 11672 c = pgetc_eatbnl();
11659 if (c == '#') { 11673 if (c == '#') {
11660 c = pgetc(); 11674 c = pgetc_eatbnl();
11661 if (c == '}') 11675 if (c == '}')
11662 c = '#'; /* ${#} - same as $# */ 11676 c = '#'; /* ${#} - same as $# */
11663 else 11677 else
@@ -11670,18 +11684,18 @@ parsesub: {
11670 /* $[{[#]]NAME[}] */ 11684 /* $[{[#]]NAME[}] */
11671 do { 11685 do {
11672 STPUTC(c, out); 11686 STPUTC(c, out);
11673 c = pgetc(); 11687 c = pgetc_eatbnl();
11674 } while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c)); 11688 } while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c));
11675 } else if (isdigit(c)) { 11689 } else if (isdigit(c)) {
11676 /* $[{[#]]NUM[}] */ 11690 /* $[{[#]]NUM[}] */
11677 do { 11691 do {
11678 STPUTC(c, out); 11692 STPUTC(c, out);
11679 c = pgetc(); 11693 c = pgetc_eatbnl();
11680 } while (isdigit(c)); 11694 } while (isdigit(c));
11681 } else if (is_special(c)) { 11695 } else if (is_special(c)) {
11682 /* $[{[#]]<specialchar>[}] */ 11696 /* $[{[#]]<specialchar>[}] */
11683 USTPUTC(c, out); 11697 USTPUTC(c, out);
11684 c = pgetc(); 11698 c = pgetc_eatbnl();
11685 } else { 11699 } else {
11686 badsub: 11700 badsub:
11687 raise_error_syntax("bad substitution"); 11701 raise_error_syntax("bad substitution");
@@ -11699,7 +11713,7 @@ parsesub: {
11699 /* c == first char after VAR */ 11713 /* c == first char after VAR */
11700 switch (c) { 11714 switch (c) {
11701 case ':': 11715 case ':':
11702 c = pgetc(); 11716 c = pgetc_eatbnl();
11703#if ENABLE_ASH_BASH_COMPAT 11717#if ENABLE_ASH_BASH_COMPAT
11704 /* This check is only needed to not misinterpret 11718 /* This check is only needed to not misinterpret
11705 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD} 11719 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
@@ -11724,7 +11738,7 @@ parsesub: {
11724 case '#': { 11738 case '#': {
11725 int cc = c; 11739 int cc = c;
11726 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT); 11740 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
11727 c = pgetc(); 11741 c = pgetc_eatbnl();
11728 if (c != cc) 11742 if (c != cc)
11729 goto do_pungetc; 11743 goto do_pungetc;
11730 subtype++; 11744 subtype++;
@@ -11736,7 +11750,7 @@ parsesub: {
11736//TODO: encode pattern and repl separately. 11750//TODO: encode pattern and repl separately.
11737// Currently ${v/$var_with_slash/repl} is horribly broken 11751// Currently ${v/$var_with_slash/repl} is horribly broken
11738 subtype = VSREPLACE; 11752 subtype = VSREPLACE;
11739 c = pgetc(); 11753 c = pgetc_eatbnl();
11740 if (c != '/') 11754 if (c != '/')
11741 goto do_pungetc; 11755 goto do_pungetc;
11742 subtype++; /* VSREPLACEALL */ 11756 subtype++; /* VSREPLACEALL */