ash: improve expandstr()
authorRon Yorston <rmy@pobox.com>
Thu, 23 Jan 2020 11:26:08 +0000 (11:26 +0000)
committerDenys Vlasenko <vda.linux@googlemail.com>
Wed, 29 Jan 2020 12:59:45 +0000 (13:59 +0100)
The dash maintainer recently posted a fix for issues with expanding
PS1.  These had already been fixed differently in BusyBox ash.  Borrow
a couple of improvements:

- Use a single call to setjmp() to trap errors in both readtoken1()
  and expandarg().

- In case of error set the prompt to the literal value of PS1 rather
  than the half-digested nonsense in stackblock() which might include
  ugly control characters.

function                                             old     new   delta
expandstr                                            353     300     -53

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c

index 4b5eafa7cbc66d07507cc04d951ae4ecd1e6101d..d6040f47ec4288dda1208f26ed0e2398aab09246 100644 (file)
@@ -13098,29 +13098,27 @@ expandstr(const char *ps, int syntax_type)
        volatile int saveint;
        struct jmploc *volatile savehandler = exception_handler;
        struct jmploc jmploc;
+       const char *volatile result;
+       int err;
 
        /* XXX Fix (char *) cast. */
        setinputstring((char *)ps);
 
        saveprompt = doprompt;
        doprompt = 0;
+       result = ps;
+
+       SAVE_INT(saveint);
+       err = setjmp(jmploc.loc);
+       if (err)
+               goto out;
 
        /* readtoken1() might die horribly.
         * Try a prompt with syntactically wrong command:
         * PS1='$(date "+%H:%M:%S) > '
         */
-       SAVE_INT(saveint);
-       if (setjmp(jmploc.loc) == 0) {
-               exception_handler = &jmploc;
-               readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
-       }
-       exception_handler = savehandler;
-       RESTORE_INT(saveint);
-
-       doprompt = saveprompt;
-
-       /* Try: PS1='`xxx(`' */
-       unwindfiles(file_stop);
+       exception_handler = &jmploc;
+       readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
 
        n.narg.type = NARG;
        n.narg.next = NULL;
@@ -13130,17 +13128,20 @@ expandstr(const char *ps, int syntax_type)
        /* expandarg() might fail too:
         * PS1='$((123+))'
         */
-       SAVE_INT(saveint);
-       if (setjmp(jmploc.loc) == 0) {
-               exception_handler = &jmploc;
-               expandarg(&n, NULL, EXP_QUOTED);
-       } else if (exception_type == EXEXIT) {
-               exitshell();
-       }
+       expandarg(&n, NULL, EXP_QUOTED);
+       result = stackblock();
+
+out:
        exception_handler = savehandler;
+       if (err && exception_type != EXERROR)
+               longjmp(exception_handler->loc, 1);
        RESTORE_INT(saveint);
 
-       return stackblock();
+       doprompt = saveprompt;
+       /* Try: PS1='`xxx(`' */
+       unwindfiles(file_stop);
+
+       return result;
 }
 
 static inline int