From 2cb4711364517add3ef204863e1993241ba18c54 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 21 Jun 2021 17:57:19 +0800 Subject: parser: Fix VSLENGTH parsing with trailing garbage On Sat, Jun 19, 2021 at 02:44:46PM +0200, Denys Vlasenko wrote: > > CTLVAR and CTLBACKQ are not properly handled if encountered > inside {$#...}. Testcase: > > dash -c "`printf 'echo ${#1\x82}'`" 00 111 222 > > It should execute "echo ${#1 }" and thus print "3" > (the length of $1, which is "111"). > > Instead, it segfaults. > > (Ideally, it should fail since "1 " is not a valid > variable name, but currently dash accepts e.g. "${#1abc}" > as if it is "${#1}bc". A separate, less serious bug...). In fact these two bugs are one and the same. This patch fixes both by detecting the invalid substitution and not emitting it into the node tree. Incidentally this reveals a bug in how we parse ${#10} that got introduced recently, which is also fixed here. Reported-by: Denys Vlasenko Fixes: 7710a926b321 ("parser: Only accept single-digit parameter...") Signed-off-by: Herbert Xu --- src/parser.c | 5 ++++- src/parser.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/parser.c b/src/parser.c index a47022e..fc9af07 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1262,7 +1262,8 @@ varname: do { STPUTC(c, out); c = pgetc_eatbnl(); - } while (!subtype && is_digit(c)); + } while ((subtype <= 0 || subtype >= VSLENGTH) && + is_digit(c)); } else if (c != '}') { int cc = c; @@ -1322,6 +1323,8 @@ varname: break; } } else { + if (subtype == VSLENGTH && c != '}') + subtype = 0; badsub: pungetc(); } diff --git a/src/parser.h b/src/parser.h index 524ac1c..7d2749b 100644 --- a/src/parser.h +++ b/src/parser.h @@ -62,6 +62,7 @@ #define VSTRIMLEFT 0x8 /* ${var#pattern} */ #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */ #define VSLENGTH 0xa /* ${#var} */ +/* VSLENGTH must come last. */ /* values of checkkwd variable */ #define CHKALIAS 0x1 -- cgit 1.4.1