ash: eval: Restore input files in evalcommand

Upstream commit:

    Date: Tue, 27 Mar 2018 00:39:35 +0800
    eval: Restore input files in evalcommand

    When evalcommand invokes a command that modifies parsefile and
    then bails out without popping the file, we need to ensure the
    input file is restored so that the shell can continue to execute.

    Reported-by: Martijn Dekker <martijn@inlv.org>
    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

function                                             old     new   delta
unwindfiles                                            -      20     +20
evalcommand                                         1635    1653     +18
getoptscmd                                           584     595     +11
popallfiles                                           20      10     -10
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/1 up/down: 49/-10)             Total: 39 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-08-05 17:07:26 +02:00
parent 58eb805c2c
commit 1c5eb88cd8

View File

@ -9942,6 +9942,7 @@ find_builtin(const char *name)
/* /*
* Execute a simple command. * Execute a simple command.
*/ */
static void unwindfiles(struct parsefile *stop);
static int static int
isassignment(const char *p) isassignment(const char *p)
{ {
@ -9964,6 +9965,7 @@ evalcommand(union node *cmd, int flags)
"\0\0", bltincmd /* why three NULs? */ "\0\0", bltincmd /* why three NULs? */
}; };
struct localvar_list *localvar_stop; struct localvar_list *localvar_stop;
struct parsefile *file_stop;
struct redirtab *redir_stop; struct redirtab *redir_stop;
struct stackmark smark; struct stackmark smark;
union node *argp; union node *argp;
@ -9989,6 +9991,7 @@ evalcommand(union node *cmd, int flags)
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
setstackmark(&smark); setstackmark(&smark);
localvar_stop = pushlocalvars(); localvar_stop = pushlocalvars();
file_stop = g_parsefile;
back_exitstatus = 0; back_exitstatus = 0;
cmdentry.cmdtype = CMDBUILTIN; cmdentry.cmdtype = CMDBUILTIN;
@ -10260,6 +10263,7 @@ evalcommand(union node *cmd, int flags)
if (cmd->ncmd.redirect) if (cmd->ncmd.redirect)
popredir(/*drop:*/ cmd_is_exec); popredir(/*drop:*/ cmd_is_exec);
unwindredir(redir_stop); unwindredir(redir_stop);
unwindfiles(file_stop);
unwindlocalvars(localvar_stop); unwindlocalvars(localvar_stop);
if (lastarg) { if (lastarg) {
/* dsl: I think this is intended to be used to support /* dsl: I think this is intended to be used to support
@ -10782,14 +10786,20 @@ popfile(void)
INT_ON; INT_ON;
} }
static void
unwindfiles(struct parsefile *stop)
{
while (g_parsefile != stop)
popfile();
}
/* /*
* Return to top level. * Return to top level.
*/ */
static void static void
popallfiles(void) popallfiles(void)
{ {
while (g_parsefile != &basepf) unwindfiles(&basepf);
popfile();
} }
/* /*