[PATCH v2 2/2] ash: catch error in arithmetic expansion in PS1

Ron Yorston rmy at pobox.com
Thu Apr 18 10:23:47 UTC 2019


Setting PS1 to:

   PS1='$((123+))'

causes the shell to enter an infinite error loop:

   sh: arithmetic syntax error

Catch any exception raised by expandarg() in expandstr() and allow
processing to continue.

If either readtoken1() or expandarg() fails return an empty string.

function                                             old     new   delta
expandstr                                            262     381    +119
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 119/0)             Total: 119 bytes

v2: If readtoken1() fails don't try expandarg().  If either fails return
    an empty string rather than part-digested nonsense.

Signed-off-by: Ron Yorston <rmy at pobox.com>
---
 shell/ash.c | 46 +++++++++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 15 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index 039524010..b375b3409 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -13043,6 +13043,10 @@ expandstr(const char *ps, int syntax_type)
 	union node n;
 	int saveprompt;
 	struct parsefile *file_stop = g_parsefile;
+	volatile int saveint;
+	struct jmploc *volatile savehandler = exception_handler;
+	struct jmploc jmploc;
+	int err;
 
 	/* XXX Fix (char *) cast. */
 	setinputstring((char *)ps);
@@ -13054,29 +13058,41 @@ expandstr(const char *ps, int syntax_type)
 	 * Try a prompt with syntactically wrong command:
 	 * PS1='$(date "+%H:%M:%S) > '
 	 */
-	{
-		volatile int saveint;
-		struct jmploc *volatile savehandler = exception_handler;
-		struct jmploc jmploc;
+	SAVE_INT(saveint);
+	err = setjmp(jmploc.loc);
+	if (err == 0) {
+		exception_handler = &jmploc;
+		readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
+	}
+	exception_handler = savehandler;
+	RESTORE_INT(saveint);
+
+	doprompt = saveprompt;
+
+	unwindfiles(file_stop);
+
+	if (err == 0) {
+		n.narg.type = NARG;
+		n.narg.next = NULL;
+		n.narg.text = wordtext;
+		n.narg.backquote = backquotelist;
+
+		/* expandarg() might fail too:
+		 * PS1='$((123+))'
+		 */
 		SAVE_INT(saveint);
-		if (setjmp(jmploc.loc) == 0) {
+		err = setjmp(jmploc.loc);
+		if (err == 0) {
 			exception_handler = &jmploc;
-			readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
+			expandarg(&n, NULL, EXP_QUOTED);
 		}
 		exception_handler = savehandler;
 		RESTORE_INT(saveint);
 	}
 
-	doprompt = saveprompt;
-
-	unwindfiles(file_stop);
-
-	n.narg.type = NARG;
-	n.narg.next = NULL;
-	n.narg.text = wordtext;
-	n.narg.backquote = backquotelist;
+	if (err)
+		*(char *)stackblock() = '\0';
 
-	expandarg(&n, NULL, EXP_QUOTED);
 	return stackblock();
 }
 
-- 
2.20.1



More information about the busybox mailing list