aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-29 22:51:52 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-29 22:51:52 +0200
commit1c79aeb6a8cae4cd4013926b97f39305b689d74c (patch)
treee23825c6a84c1c95c2285fc54e5cce4f129660f7 /shell
parent469998015f57a552718420a4050d90e5dae6a6fd (diff)
downloadbusybox-w32-1c79aeb6a8cae4cd4013926b97f39305b689d74c.tar.gz
busybox-w32-1c79aeb6a8cae4cd4013926b97f39305b689d74c.tar.bz2
busybox-w32-1c79aeb6a8cae4cd4013926b97f39305b689d74c.zip
ash: [REDIR] Fix popredir on abnormal exit from built-in
Upstream commit: Date: Thu, 27 May 2010 15:03:46 +0800 [REDIR] Fix popredir on abnormal exit from built-in Just like the poplocalvar problem recently fixed, redirections can also be leaked in case of an abnormal exit. This patch fixes it using the same method as poplocalvar, by storing the previous redirection state and restoring to that point. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c70
1 files changed, 44 insertions, 26 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 3184249f5..e2b4eee95 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -5435,33 +5435,13 @@ redirect(union node *redir, int flags)
5435 int newfd; 5435 int newfd;
5436 int copied_fd2 = -1; 5436 int copied_fd2 = -1;
5437 5437
5438 if (!redir) { 5438 if (!redir)
5439 return; 5439 return;
5440 }
5441
5442 sv = NULL; 5440 sv = NULL;
5443 sv_pos = 0;
5444 INT_OFF; 5441 INT_OFF;
5445 if (flags & REDIR_PUSH) { 5442 if (flags & REDIR_PUSH)
5446 union node *tmp = redir; 5443 sv = redirlist;
5447 do { 5444 sv_pos = 0;
5448 sv_pos++;
5449#if BASH_REDIR_OUTPUT
5450 if (tmp->nfile.type == NTO2)
5451 sv_pos++;
5452#endif
5453 tmp = tmp->nfile.next;
5454 } while (tmp);
5455 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5456 sv->next = redirlist;
5457 sv->pair_count = sv_pos;
5458 redirlist = sv;
5459 while (sv_pos > 0) {
5460 sv_pos--;
5461 sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5462 }
5463 }
5464
5465 do { 5445 do {
5466 int right_fd = -1; 5446 int right_fd = -1;
5467 fd = redir->nfile.fd; 5447 fd = redir->nfile.fd;
@@ -5583,6 +5563,34 @@ redirectsafe(union node *redir, int flags)
5583 return err; 5563 return err;
5584} 5564}
5585 5565
5566static struct redirtab*
5567pushredir(union node *redir)
5568{
5569 struct redirtab *sv;
5570 int i;
5571
5572 if (!redir)
5573 return redirlist;
5574
5575 i = 0;
5576 do {
5577 i++;
5578#if BASH_REDIR_OUTPUT
5579 if (redir->nfile.type == NTO2)
5580 i++;
5581#endif
5582 redir = redir->nfile.next;
5583 } while (redir);
5584
5585 sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5586 sv->pair_count = i;
5587 while (--i >= 0)
5588 sv->two_fd[i].orig = sv->two_fd[i].copy = EMPTY;
5589 sv->next = redirlist;
5590 redirlist = sv;
5591 return sv->next;
5592}
5593
5586/* 5594/*
5587 * Undo the effects of the last redirection. 5595 * Undo the effects of the last redirection.
5588 */ 5596 */
@@ -5618,6 +5626,13 @@ popredir(int drop, int restore)
5618 INT_ON; 5626 INT_ON;
5619} 5627}
5620 5628
5629static void
5630unwindredir(struct redirtab *stop)
5631{
5632 while (redirlist != stop)
5633 popredir(/*drop:*/ 0, /*restore:*/ 0);
5634}
5635
5621 5636
5622/* ============ Routines to expand arguments to commands 5637/* ============ Routines to expand arguments to commands
5623 * 5638 *
@@ -8727,6 +8742,7 @@ evaltree(union node *n, int flags)
8727 goto setstatus; 8742 goto setstatus;
8728 case NREDIR: 8743 case NREDIR:
8729 expredir(n->nredir.redirect); 8744 expredir(n->nredir.redirect);
8745 pushredir(n->nredir.redirect);
8730 status = redirectsafe(n->nredir.redirect, REDIR_PUSH); 8746 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8731 if (!status) { 8747 if (!status) {
8732 status = evaltree(n->nredir.n, flags & EV_TESTED); 8748 status = evaltree(n->nredir.n, flags & EV_TESTED);
@@ -9622,6 +9638,7 @@ evalcommand(union node *cmd, int flags)
9622 "\0\0", bltincmd /* why three NULs? */ 9638 "\0\0", bltincmd /* why three NULs? */
9623 }; 9639 };
9624 struct localvar_list *localvar_stop; 9640 struct localvar_list *localvar_stop;
9641 struct redirtab *redir_stop;
9625 struct stackmark smark; 9642 struct stackmark smark;
9626 union node *argp; 9643 union node *argp;
9627 struct arglist arglist; 9644 struct arglist arglist;
@@ -9687,6 +9704,7 @@ evalcommand(union node *cmd, int flags)
9687 9704
9688 preverrout_fd = 2; 9705 preverrout_fd = 2;
9689 expredir(cmd->ncmd.redirect); 9706 expredir(cmd->ncmd.redirect);
9707 redir_stop = pushredir(cmd->ncmd.redirect);
9690 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2); 9708 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9691 9709
9692 path = vpath.var_text; 9710 path = vpath.var_text;
@@ -9878,6 +9896,7 @@ evalcommand(union node *cmd, int flags)
9878 out: 9896 out:
9879 if (cmd->ncmd.redirect) 9897 if (cmd->ncmd.redirect)
9880 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec); 9898 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9899 unwindredir(redir_stop);
9881 unwindlocalvars(localvar_stop); 9900 unwindlocalvars(localvar_stop);
9882 if (lastarg) { 9901 if (lastarg) {
9883 /* dsl: I think this is intended to be used to support 9902 /* dsl: I think this is intended to be used to support
@@ -13584,8 +13603,7 @@ reset(void)
13584 popallfiles(); 13603 popallfiles();
13585 13604
13586 /* from redir.c: */ 13605 /* from redir.c: */
13587 while (redirlist) 13606 unwindredir(NULL);
13588 popredir(/*drop:*/ 0, /*restore:*/ 0);
13589 13607
13590 /* from var.c: */ 13608 /* from var.c: */
13591 unwindlocalvars(NULL); 13609 unwindlocalvars(NULL);