ash: eval: Restore input files in evalcommand
authorDenys Vlasenko <vda.linux@googlemail.com>
Sun, 5 Aug 2018 15:07:26 +0000 (17:07 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sun, 5 Aug 2018 16:11:15 +0000 (18:11 +0200)
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>
shell/ash.c

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