diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-29 22:51:52 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-29 22:51:52 +0200 |
commit | 1c79aeb6a8cae4cd4013926b97f39305b689d74c (patch) | |
tree | e23825c6a84c1c95c2285fc54e5cce4f129660f7 /shell | |
parent | 469998015f57a552718420a4050d90e5dae6a6fd (diff) | |
download | busybox-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.c | 70 |
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 | ||
5566 | static struct redirtab* | ||
5567 | pushredir(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 | ||
5629 | static void | ||
5630 | unwindredir(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); |