[git commit] hush: fix bkslash+newline handling and number validation in ${NN} and ${#NN}

Denys Vlasenko vda.linux at googlemail.com
Sat Jun 19 13:45:45 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=97c3b5e3ff252b3399d10835d5c906886a7499f4
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Entering "${1a}" into interactive shell was making it exit.

function                                             old     new   delta
parse_dollar                                         824     958    +134
i_getch_and_eat_bkslash_nl                             -      44     +44
parse_expr                                           917     938     +21
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/0 up/down: 199/0)             Total: 199 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/ash_test/ash-parsing/bkslash_newline4.right  |  4 ++++
 shell/ash_test/ash-parsing/bkslash_newline4.tests  | 14 +++++++++++
 shell/hush.c                                       | 28 +++++++++++++++++++++-
 .../hush_test/hush-parsing/bkslash_newline4.right  |  4 ++++
 .../hush_test/hush-parsing/bkslash_newline4.tests  | 14 +++++++++++
 shell/hush_test/hush-vars/var6.right               |  2 +-
 6 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/shell/ash_test/ash-parsing/bkslash_newline4.right b/shell/ash_test/ash-parsing/bkslash_newline4.right
new file mode 100644
index 000000000..2110716d1
--- /dev/null
+++ b/shell/ash_test/ash-parsing/bkslash_newline4.right
@@ -0,0 +1,4 @@
+1:1
+22:22
+3:3
+Ok:0
diff --git a/shell/ash_test/ash-parsing/bkslash_newline4.tests b/shell/ash_test/ash-parsing/bkslash_newline4.tests
new file mode 100755
index 000000000..c8f5037c4
--- /dev/null
+++ b/shell/ash_test/ash-parsing/bkslash_newline4.tests
@@ -0,0 +1,14 @@
+set -- 1 22 333
+echo 1:$\
+1
+echo 22:$\
+{\
+2\
+}
+echo 3:$\
+{\
+#\
+3\
+}
+echo Ok:$\
+?
diff --git a/shell/hush.c b/shell/hush.c
index e8d24d40b..1aa0a400d 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -4998,6 +4998,32 @@ static int parse_dollar(o_string *as_string,
 		 * which check invalid constructs like ${%}.
 		 * Oh well... let's check that the var name part is fine... */
 
+		if (isdigit(len_single_ch)
+		 || (len_single_ch == '#' && isdigit(i_peek_and_eat_bkslash_nl(input)))
+		) {
+			/* Execution engine uses plain xatoi_positive()
+			 * to interpret ${NNN} and {#NNN},
+			 * check syntax here in the parser.
+			 * (bash does not support expressions in ${#NN},
+			 * e.g. ${#$var} and {#1:+WORD} are not supported).
+			 */
+			unsigned cnt = 9; /* max 9 digits for ${NN} and 8 for {#NN} */
+			while (1) {
+				o_addchr(dest, ch);
+				debug_printf_parse(": '%c'\n", ch);
+				ch = i_getch_and_eat_bkslash_nl(input);
+				nommu_addchr(as_string, ch);
+				if (ch == '}')
+					break;
+				if (--cnt == 0)
+					goto bad_dollar_syntax;
+				if (len_single_ch != '#' && strchr(VAR_SUBST_OPS, ch))
+					/* ${NN<op>...} is valid */
+					goto eat_until_closing;
+				if (!isdigit(ch))
+					goto bad_dollar_syntax;
+			}
+		} else
 		while (1) {
 			unsigned pos;
 
@@ -5008,7 +5034,6 @@ static int parse_dollar(o_string *as_string,
 			nommu_addchr(as_string, ch);
 			if (ch == '}')
 				break;
-
 			if (!isalnum(ch) && ch != '_') {
 				unsigned end_ch;
 				unsigned char last_ch;
@@ -5027,6 +5052,7 @@ static int parse_dollar(o_string *as_string,
 					 * special var name, e.g. ${#!}.
 					 */
 				}
+ eat_until_closing:
 				/* Eat everything until closing '}' (or ':') */
 				end_ch = '}';
 				if (BASH_SUBSTR
diff --git a/shell/hush_test/hush-parsing/bkslash_newline4.right b/shell/hush_test/hush-parsing/bkslash_newline4.right
new file mode 100644
index 000000000..2110716d1
--- /dev/null
+++ b/shell/hush_test/hush-parsing/bkslash_newline4.right
@@ -0,0 +1,4 @@
+1:1
+22:22
+3:3
+Ok:0
diff --git a/shell/hush_test/hush-parsing/bkslash_newline4.tests b/shell/hush_test/hush-parsing/bkslash_newline4.tests
new file mode 100755
index 000000000..c8f5037c4
--- /dev/null
+++ b/shell/hush_test/hush-parsing/bkslash_newline4.tests
@@ -0,0 +1,14 @@
+set -- 1 22 333
+echo 1:$\
+1
+echo 22:$\
+{\
+2\
+}
+echo 3:$\
+{\
+#\
+3\
+}
+echo Ok:$\
+?
diff --git a/shell/hush_test/hush-vars/var6.right b/shell/hush_test/hush-vars/var6.right
index 40e67fdf5..5e28d2fab 100644
--- a/shell/hush_test/hush-vars/var6.right
+++ b/shell/hush_test/hush-vars/var6.right
@@ -1,2 +1,2 @@
-hush: invalid number '1q'
+hush: syntax error: unterminated ${name}
 hush: syntax error: unterminated ${name}


More information about the busybox-cvs mailing list