ash: improve expandstr()

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>
This commit is contained in:
Ron Yorston 2020-01-23 11:26:08 +00:00 committed by Denys Vlasenko
parent eb7f9acda1
commit b0c711e64f

View 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