diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-18 16:13:56 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-18 16:13:56 +0200 |
commit | 42c4b2e3b535314ae8a7b65c3223afb26872d5a2 (patch) | |
tree | 8c0d1b5eef44dc9dbce6788fe41db1af22bbf470 /shell | |
parent | c7f95d23f6bc7e17a3b79decf83eb362b389e53a (diff) | |
download | busybox-w32-42c4b2e3b535314ae8a7b65c3223afb26872d5a2.tar.gz busybox-w32-42c4b2e3b535314ae8a7b65c3223afb26872d5a2.tar.bz2 busybox-w32-42c4b2e3b535314ae8a7b65c3223afb26872d5a2.zip |
ash: fix var_leak.tests so that it actually catches the NOFORK bug
+ document the bug better
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 22 | ||||
-rw-r--r-- | shell/ash_test/ash-vars/var_leak.right | 1 | ||||
-rwxr-xr-x | shell/ash_test/ash-vars/var_leak.tests | 7 |
3 files changed, 21 insertions, 9 deletions
diff --git a/shell/ash.c b/shell/ash.c index d082333ba..83886c610 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -9179,12 +9179,14 @@ evalcommand(union node *cmd, int flags) | |||
9179 | 9179 | ||
9180 | /* Execute the command. */ | 9180 | /* Execute the command. */ |
9181 | switch (cmdentry.cmdtype) { | 9181 | switch (cmdentry.cmdtype) { |
9182 | default: | 9182 | default: { |
9183 | 9183 | ||
9184 | #if ENABLE_FEATURE_SH_NOFORK | 9184 | #if ENABLE_FEATURE_SH_NOFORK |
9185 | /* Hmmm... shouldn't it happen somewhere in forkshell() instead? | 9185 | /* (1) BUG: if variables are set, we need to fork, or save/restore them |
9186 | * Why "fork off a child process if necessary" doesn't apply to NOFORK? */ | 9186 | * around run_nofork_applet() call. |
9187 | { | 9187 | * (2) Should this check also be done in forkshell()? |
9188 | * (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...) | ||
9189 | */ | ||
9188 | /* find_command() encodes applet_no as (-2 - applet_no) */ | 9190 | /* find_command() encodes applet_no as (-2 - applet_no) */ |
9189 | int applet_no = (- cmdentry.u.index - 2); | 9191 | int applet_no = (- cmdentry.u.index - 2); |
9190 | if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { | 9192 | if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { |
@@ -9193,10 +9195,13 @@ evalcommand(union node *cmd, int flags) | |||
9193 | exitstatus = run_nofork_applet(applet_no, argv); | 9195 | exitstatus = run_nofork_applet(applet_no, argv); |
9194 | break; | 9196 | break; |
9195 | } | 9197 | } |
9196 | } | ||
9197 | #endif | 9198 | #endif |
9198 | /* Fork off a child process if necessary. */ | 9199 | /* Can we avoid forking off? For example, very last command |
9200 | * in a script or a subshell does not need forking, | ||
9201 | * we can just exec it. | ||
9202 | */ | ||
9199 | if (!(flags & EV_EXIT) || may_have_traps) { | 9203 | if (!(flags & EV_EXIT) || may_have_traps) { |
9204 | /* No, forking off a child is necessary */ | ||
9200 | INT_OFF; | 9205 | INT_OFF; |
9201 | jp = makejob(/*cmd,*/ 1); | 9206 | jp = makejob(/*cmd,*/ 1); |
9202 | if (forkshell(jp, cmd, FORK_FG) != 0) { | 9207 | if (forkshell(jp, cmd, FORK_FG) != 0) { |
@@ -9213,7 +9218,7 @@ evalcommand(union node *cmd, int flags) | |||
9213 | listsetvar(varlist.list, VEXPORT|VSTACK); | 9218 | listsetvar(varlist.list, VEXPORT|VSTACK); |
9214 | shellexec(argv, path, cmdentry.u.index); | 9219 | shellexec(argv, path, cmdentry.u.index); |
9215 | /* NOTREACHED */ | 9220 | /* NOTREACHED */ |
9216 | 9221 | } /* default */ | |
9217 | case CMDBUILTIN: | 9222 | case CMDBUILTIN: |
9218 | cmdenviron = varlist.list; | 9223 | cmdenviron = varlist.list; |
9219 | if (cmdenviron) { | 9224 | if (cmdenviron) { |
@@ -9258,7 +9263,8 @@ evalcommand(union node *cmd, int flags) | |||
9258 | if (evalfun(cmdentry.u.func, argc, argv, flags)) | 9263 | if (evalfun(cmdentry.u.func, argc, argv, flags)) |
9259 | goto raise; | 9264 | goto raise; |
9260 | break; | 9265 | break; |
9261 | } | 9266 | |
9267 | } /* switch */ | ||
9262 | 9268 | ||
9263 | out: | 9269 | out: |
9264 | popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec); | 9270 | popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec); |
diff --git a/shell/ash_test/ash-vars/var_leak.right b/shell/ash_test/ash-vars/var_leak.right index be78112c8..01a5e3263 100644 --- a/shell/ash_test/ash-vars/var_leak.right +++ b/shell/ash_test/ash-vars/var_leak.right | |||
@@ -1,3 +1,4 @@ | |||
1 | should be empty: '' | 1 | should be empty: '' |
2 | should be empty: '' | ||
2 | should be not empty: 'val2' | 3 | should be not empty: 'val2' |
3 | should be not empty: 'val3' | 4 | should be not empty: 'val3' |
diff --git a/shell/ash_test/ash-vars/var_leak.tests b/shell/ash_test/ash-vars/var_leak.tests index 032059295..5242e24eb 100755 --- a/shell/ash_test/ash-vars/var_leak.tests +++ b/shell/ash_test/ash-vars/var_leak.tests | |||
@@ -1,6 +1,11 @@ | |||
1 | # true is a regular builtin, varibale should not leak out of it | 1 | # cat is an external program, variable should not leak out of it. |
2 | # this currently fails with CONFIG_FEATURE_SH_NOFORK=y | 2 | # this currently fails with CONFIG_FEATURE_SH_NOFORK=y |
3 | VAR='' | 3 | VAR='' |
4 | VAR=val0 cat /dev/null | ||
5 | echo "should be empty: '$VAR'" | ||
6 | |||
7 | # true is a regular builtin, variable should not leak out of it. | ||
8 | VAR='' | ||
4 | VAR=val1 true | 9 | VAR=val1 true |
5 | echo "should be empty: '$VAR'" | 10 | echo "should be empty: '$VAR'" |
6 | 11 | ||