diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-04 00:14:30 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-04 00:14:30 +0200 |
commit | cb6ff25afeb2daeebcb435c9766215061d3c75cb (patch) | |
tree | e185f3ff23622f171d52fb783ad4b23626f26bfc /shell | |
parent | e19e1935a33b117e2ee6daf9b2d79c00603333c7 (diff) | |
download | busybox-w32-cb6ff25afeb2daeebcb435c9766215061d3c75cb.tar.gz busybox-w32-cb6ff25afeb2daeebcb435c9766215061d3c75cb.tar.bz2 busybox-w32-cb6ff25afeb2daeebcb435c9766215061d3c75cb.zip |
hush: fix bug where in "var=val func" var's value is not visible in func
function old new delta
unset_local_var - 168 +168
set_vars_all_and_save_old - 87 +87
get_ptr_to_local_var - 77 +77
free_strings_and_unset - 53 +53
builtin_export 266 274 +8
get_local_var_value 31 33 +2
putenv_all 27 - -27
free_strings_and_unsetenv 53 - -53
get_local_var 68 - -68
run_list 2475 2350 -125
builtin_unset 380 220 -160
------------------------------------------------------------------------------
(add/remove: 4/3 grow/shrink: 2/2 up/down: 395/-433) Total: -38 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 199 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/env_and_func.right (renamed from shell/hush_test/hush-bugs/env_and_func.right) | 0 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/env_and_func.tests (renamed from shell/hush_test/hush-bugs/env_and_func.tests) | 2 |
3 files changed, 109 insertions, 92 deletions
diff --git a/shell/hush.c b/shell/hush.c index c6e940548..0890f0977 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -56,7 +56,7 @@ | |||
56 | * | 56 | * |
57 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | 57 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
58 | */ | 58 | */ |
59 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ | 59 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ |
60 | #include <glob.h> | 60 | #include <glob.h> |
61 | /* #include <dmalloc.h> */ | 61 | /* #include <dmalloc.h> */ |
62 | #if ENABLE_HUSH_CASE | 62 | #if ENABLE_HUSH_CASE |
@@ -65,7 +65,7 @@ | |||
65 | #include "math.h" | 65 | #include "math.h" |
66 | #include "match.h" | 66 | #include "match.h" |
67 | #ifndef PIPE_BUF | 67 | #ifndef PIPE_BUF |
68 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ | 68 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ |
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | 71 | ||
@@ -138,6 +138,8 @@ | |||
138 | 138 | ||
139 | #define SPECIAL_VAR_SYMBOL 3 | 139 | #define SPECIAL_VAR_SYMBOL 3 |
140 | 140 | ||
141 | struct variable; | ||
142 | |||
141 | static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER; | 143 | static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER; |
142 | 144 | ||
143 | /* This supports saving pointers malloced in vfork child, | 145 | /* This supports saving pointers malloced in vfork child, |
@@ -146,7 +148,7 @@ static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER; | |||
146 | #if !BB_MMU | 148 | #if !BB_MMU |
147 | typedef struct nommu_save_t { | 149 | typedef struct nommu_save_t { |
148 | char **new_env; | 150 | char **new_env; |
149 | char **old_env; | 151 | struct variable *old_vars; |
150 | char **argv; | 152 | char **argv; |
151 | char **argv_from_re_execing; | 153 | char **argv_from_re_execing; |
152 | } nommu_save_t; | 154 | } nommu_save_t; |
@@ -282,8 +284,8 @@ struct command { | |||
282 | #if ENABLE_HUSH_FUNCTIONS | 284 | #if ENABLE_HUSH_FUNCTIONS |
283 | # define GRP_FUNCTION 2 | 285 | # define GRP_FUNCTION 2 |
284 | #endif | 286 | #endif |
285 | struct pipe *group; /* if non-NULL, this "command" is { list }, | 287 | /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */ |
286 | * ( list ), or a compound statement */ | 288 | struct pipe *group; |
287 | #if !BB_MMU | 289 | #if !BB_MMU |
288 | char *group_as_string; | 290 | char *group_as_string; |
289 | #endif | 291 | #endif |
@@ -883,6 +885,7 @@ static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, | |||
883 | xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup) | 885 | xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup) |
884 | #endif | 886 | #endif |
885 | 887 | ||
888 | /* Note: takes ownership of "add" ptr (it is not strdup'ed) */ | ||
886 | static char **add_string_to_strings(char **strings, char *add) | 889 | static char **add_string_to_strings(char **strings, char *add) |
887 | { | 890 | { |
888 | char *v[2]; | 891 | char *v[2]; |
@@ -901,44 +904,9 @@ static char **xx_add_string_to_strings(int lineno, char **strings, char *add) | |||
901 | xx_add_string_to_strings(__LINE__, strings, add) | 904 | xx_add_string_to_strings(__LINE__, strings, add) |
902 | #endif | 905 | #endif |
903 | 906 | ||
904 | static void putenv_all(char **strings) | 907 | static int unset_local_var(const char *name); |
905 | { | ||
906 | if (!strings) | ||
907 | return; | ||
908 | while (*strings) { | ||
909 | debug_printf_env("putenv '%s'\n", *strings); | ||
910 | putenv(*strings++); | ||
911 | } | ||
912 | } | ||
913 | |||
914 | static char **putenv_all_and_save_old(char **strings) | ||
915 | { | ||
916 | char **old = NULL; | ||
917 | char **s = strings; | ||
918 | |||
919 | if (!strings) | ||
920 | return old; | ||
921 | while (*strings) { | ||
922 | char *v, *eq; | ||
923 | |||
924 | eq = strchr(*strings, '='); | ||
925 | if (eq) { | ||
926 | *eq = '\0'; | ||
927 | v = getenv(*strings); | ||
928 | *eq = '='; | ||
929 | if (v) { | ||
930 | /* v points to VAL in VAR=VAL, go back to VAR */ | ||
931 | v -= (eq - *strings) + 1; | ||
932 | old = add_string_to_strings(old, v); | ||
933 | } | ||
934 | } | ||
935 | strings++; | ||
936 | } | ||
937 | putenv_all(s); | ||
938 | return old; | ||
939 | } | ||
940 | 908 | ||
941 | static void free_strings_and_unsetenv(char **strings, int unset) | 909 | static void free_strings_and_unset(char **strings, int unset) |
942 | { | 910 | { |
943 | char **v; | 911 | char **v; |
944 | 912 | ||
@@ -948,8 +916,7 @@ static void free_strings_and_unsetenv(char **strings, int unset) | |||
948 | v = strings; | 916 | v = strings; |
949 | while (*v) { | 917 | while (*v) { |
950 | if (unset) { | 918 | if (unset) { |
951 | debug_printf_env("unsetenv '%s'\n", *v); | 919 | unset_local_var(*v); |
952 | bb_unsetenv(*v); | ||
953 | } | 920 | } |
954 | free(*v++); | 921 | free(*v++); |
955 | } | 922 | } |
@@ -958,7 +925,7 @@ static void free_strings_and_unsetenv(char **strings, int unset) | |||
958 | 925 | ||
959 | static void free_strings(char **strings) | 926 | static void free_strings(char **strings) |
960 | { | 927 | { |
961 | free_strings_and_unsetenv(strings, 0); | 928 | free_strings_and_unset(strings, 0); |
962 | } | 929 | } |
963 | 930 | ||
964 | 931 | ||
@@ -1242,27 +1209,38 @@ static const char *set_cwd(void) | |||
1242 | } | 1209 | } |
1243 | 1210 | ||
1244 | 1211 | ||
1245 | /* Get/check local shell variables */ | 1212 | /* |
1246 | static struct variable *get_local_var(const char *name) | 1213 | * Shell and environment variable support |
1214 | */ | ||
1215 | static struct variable **get_ptr_to_local_var(const char *name) | ||
1247 | { | 1216 | { |
1217 | struct variable **pp; | ||
1248 | struct variable *cur; | 1218 | struct variable *cur; |
1249 | int len; | 1219 | int len; |
1250 | 1220 | ||
1251 | if (!name) | ||
1252 | return NULL; | ||
1253 | len = strlen(name); | 1221 | len = strlen(name); |
1254 | for (cur = G.top_var; cur; cur = cur->next) { | 1222 | pp = &G.top_var; |
1223 | while ((cur = *pp) != NULL) { | ||
1255 | if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') | 1224 | if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') |
1256 | return cur; | 1225 | return pp; |
1226 | pp = &cur->next; | ||
1257 | } | 1227 | } |
1258 | return NULL; | 1228 | return NULL; |
1259 | } | 1229 | } |
1260 | 1230 | ||
1261 | static const char *get_local_var_value(const char *src) | 1231 | static struct variable *get_local_var(const char *name) |
1262 | { | 1232 | { |
1263 | struct variable *var = get_local_var(src); | 1233 | struct variable **pp = get_ptr_to_local_var(name); |
1264 | if (var) | 1234 | if (pp) |
1265 | return strchr(var->varstr, '=') + 1; | 1235 | return *pp; |
1236 | return NULL; | ||
1237 | } | ||
1238 | |||
1239 | static const char *get_local_var_value(const char *name) | ||
1240 | { | ||
1241 | struct variable **pp = get_ptr_to_local_var(name); | ||
1242 | if (pp) | ||
1243 | return strchr((*pp)->varstr, '=') + 1; | ||
1266 | return NULL; | 1244 | return NULL; |
1267 | } | 1245 | } |
1268 | 1246 | ||
@@ -1423,6 +1401,57 @@ static void arith_set_local_var(const char *name, const char *val, int flags) | |||
1423 | 1401 | ||
1424 | 1402 | ||
1425 | /* | 1403 | /* |
1404 | * Helpers for "var1=val1 var2=val2 cmd" feature | ||
1405 | */ | ||
1406 | static void add_vars(struct variable *var) | ||
1407 | { | ||
1408 | struct variable *next; | ||
1409 | |||
1410 | while (var) { | ||
1411 | next = var->next; | ||
1412 | var->next = G.top_var; | ||
1413 | G.top_var = var; | ||
1414 | if (var->flg_export) | ||
1415 | putenv(var->varstr); | ||
1416 | var = next; | ||
1417 | } | ||
1418 | } | ||
1419 | |||
1420 | static struct variable *set_vars_all_and_save_old(char **strings) | ||
1421 | { | ||
1422 | char **s; | ||
1423 | struct variable *old = NULL; | ||
1424 | |||
1425 | if (!strings) | ||
1426 | return old; | ||
1427 | s = strings; | ||
1428 | while (*s) { | ||
1429 | struct variable *var_p; | ||
1430 | struct variable **var_pp; | ||
1431 | char *eq; | ||
1432 | |||
1433 | eq = strchr(*s, '='); | ||
1434 | if (eq) { | ||
1435 | *eq = '\0'; | ||
1436 | var_pp = get_ptr_to_local_var(*s); | ||
1437 | *eq = '='; | ||
1438 | if (var_pp) { | ||
1439 | /* Remove variable from global linked list */ | ||
1440 | var_p = *var_pp; | ||
1441 | *var_pp = var_p->next; | ||
1442 | /* Add it to returned list */ | ||
1443 | var_p->next = old; | ||
1444 | old = var_p; | ||
1445 | } | ||
1446 | set_local_var(*s, 1, 0); | ||
1447 | } | ||
1448 | s++; | ||
1449 | } | ||
1450 | return old; | ||
1451 | } | ||
1452 | |||
1453 | |||
1454 | /* | ||
1426 | * in_str support | 1455 | * in_str support |
1427 | */ | 1456 | */ |
1428 | static int static_get(struct in_str *i) | 1457 | static int static_get(struct in_str *i) |
@@ -2855,17 +2884,17 @@ static struct function *new_function(char *name) | |||
2855 | * body_as_string was not malloced! */ | 2884 | * body_as_string was not malloced! */ |
2856 | if (funcp->body) { | 2885 | if (funcp->body) { |
2857 | free_pipe_list(funcp->body); | 2886 | free_pipe_list(funcp->body); |
2858 | #if !BB_MMU | 2887 | # if !BB_MMU |
2859 | free(funcp->body_as_string); | 2888 | free(funcp->body_as_string); |
2860 | #endif | 2889 | # endif |
2861 | } | 2890 | } |
2862 | } else { | 2891 | } else { |
2863 | debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name); | 2892 | debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name); |
2864 | cmd->argv[0] = funcp->name; | 2893 | cmd->argv[0] = funcp->name; |
2865 | cmd->group = funcp->body; | 2894 | cmd->group = funcp->body; |
2866 | #if !BB_MMU | 2895 | # if !BB_MMU |
2867 | cmd->group_as_string = funcp->body_as_string; | 2896 | cmd->group_as_string = funcp->body_as_string; |
2868 | #endif | 2897 | # endif |
2869 | } | 2898 | } |
2870 | goto skip; | 2899 | goto skip; |
2871 | } | 2900 | } |
@@ -2892,9 +2921,9 @@ static void unset_func(const char *name) | |||
2892 | * body_as_string was not malloced! */ | 2921 | * body_as_string was not malloced! */ |
2893 | if (funcp->body) { | 2922 | if (funcp->body) { |
2894 | free_pipe_list(funcp->body); | 2923 | free_pipe_list(funcp->body); |
2895 | #if !BB_MMU | 2924 | # if !BB_MMU |
2896 | free(funcp->body_as_string); | 2925 | free(funcp->body_as_string); |
2897 | #endif | 2926 | # endif |
2898 | } | 2927 | } |
2899 | free(funcp); | 2928 | free(funcp); |
2900 | break; | 2929 | break; |
@@ -2903,10 +2932,10 @@ static void unset_func(const char *name) | |||
2903 | } | 2932 | } |
2904 | } | 2933 | } |
2905 | 2934 | ||
2906 | #if BB_MMU | 2935 | # if BB_MMU |
2907 | #define exec_function(nommu_save, funcp, argv) \ | 2936 | #define exec_function(nommu_save, funcp, argv) \ |
2908 | exec_function(funcp, argv) | 2937 | exec_function(funcp, argv) |
2909 | #endif | 2938 | # endif |
2910 | static void exec_function(nommu_save_t *nommu_save, | 2939 | static void exec_function(nommu_save_t *nommu_save, |
2911 | const struct function *funcp, | 2940 | const struct function *funcp, |
2912 | char **argv) NORETURN; | 2941 | char **argv) NORETURN; |
@@ -2938,37 +2967,31 @@ static int run_function(const struct function *funcp, char **argv) | |||
2938 | { | 2967 | { |
2939 | int rc; | 2968 | int rc; |
2940 | save_arg_t sv; | 2969 | save_arg_t sv; |
2941 | #if ENABLE_HUSH_FUNCTIONS | ||
2942 | smallint sv_flg; | 2970 | smallint sv_flg; |
2943 | #endif | ||
2944 | 2971 | ||
2945 | save_and_replace_G_args(&sv, argv); | 2972 | save_and_replace_G_args(&sv, argv); |
2946 | #if ENABLE_HUSH_FUNCTIONS | ||
2947 | /* "we are in function, ok to use return" */ | 2973 | /* "we are in function, ok to use return" */ |
2948 | sv_flg = G.flag_return_in_progress; | 2974 | sv_flg = G.flag_return_in_progress; |
2949 | G.flag_return_in_progress = -1; | 2975 | G.flag_return_in_progress = -1; |
2950 | #endif | ||
2951 | 2976 | ||
2952 | /* On MMU, funcp->body is always non-NULL */ | 2977 | /* On MMU, funcp->body is always non-NULL */ |
2953 | #if !BB_MMU | 2978 | # if !BB_MMU |
2954 | if (!funcp->body) { | 2979 | if (!funcp->body) { |
2955 | /* Function defined by -F */ | 2980 | /* Function defined by -F */ |
2956 | parse_and_run_string(funcp->body_as_string); | 2981 | parse_and_run_string(funcp->body_as_string); |
2957 | rc = G.last_exitcode; | 2982 | rc = G.last_exitcode; |
2958 | } else | 2983 | } else |
2959 | #endif | 2984 | # endif |
2960 | { | 2985 | { |
2961 | rc = run_list(funcp->body); | 2986 | rc = run_list(funcp->body); |
2962 | } | 2987 | } |
2963 | 2988 | ||
2964 | #if ENABLE_HUSH_FUNCTIONS | ||
2965 | G.flag_return_in_progress = sv_flg; | 2989 | G.flag_return_in_progress = sv_flg; |
2966 | #endif | ||
2967 | restore_G_args(&sv, argv); | 2990 | restore_G_args(&sv, argv); |
2968 | 2991 | ||
2969 | return rc; | 2992 | return rc; |
2970 | } | 2993 | } |
2971 | #endif | 2994 | #endif /* ENABLE_HUSH_FUNCTIONS */ |
2972 | 2995 | ||
2973 | 2996 | ||
2974 | #if BB_MMU | 2997 | #if BB_MMU |
@@ -2998,11 +3021,13 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save, | |||
2998 | 3021 | ||
2999 | new_env = expand_assignments(argv, assignment_cnt); | 3022 | new_env = expand_assignments(argv, assignment_cnt); |
3000 | #if BB_MMU | 3023 | #if BB_MMU |
3001 | putenv_all(new_env); | 3024 | set_vars_all_and_save_old(new_env); |
3002 | free(new_env); /* optional */ | 3025 | free(new_env); /* optional */ |
3026 | /* we can also destroy set_vars_all_and_save_old's return value, | ||
3027 | * to save memory */ | ||
3003 | #else | 3028 | #else |
3004 | nommu_save->new_env = new_env; | 3029 | nommu_save->new_env = new_env; |
3005 | nommu_save->old_env = putenv_all_and_save_old(new_env); | 3030 | nommu_save->old_vars = set_vars_all_and_save_old(new_env); |
3006 | #endif | 3031 | #endif |
3007 | if (argv_expanded) { | 3032 | if (argv_expanded) { |
3008 | argv = argv_expanded; | 3033 | argv = argv_expanded; |
@@ -3443,10 +3468,10 @@ static int run_pipe(struct pipe *pi) | |||
3443 | funcp = new_function(command->argv[0]); | 3468 | funcp = new_function(command->argv[0]); |
3444 | /* funcp->name is already set to argv[0] */ | 3469 | /* funcp->name is already set to argv[0] */ |
3445 | funcp->body = command->group; | 3470 | funcp->body = command->group; |
3446 | #if !BB_MMU | 3471 | # if !BB_MMU |
3447 | funcp->body_as_string = command->group_as_string; | 3472 | funcp->body_as_string = command->group_as_string; |
3448 | command->group_as_string = NULL; | 3473 | command->group_as_string = NULL; |
3449 | #endif | 3474 | # endif |
3450 | command->group = NULL; | 3475 | command->group = NULL; |
3451 | command->argv[0] = NULL; | 3476 | command->argv[0] = NULL; |
3452 | debug_printf_exec("cmd %p has child func at %p\n", command, funcp); | 3477 | debug_printf_exec("cmd %p has child func at %p\n", command, funcp); |
@@ -3481,7 +3506,7 @@ static int run_pipe(struct pipe *pi) | |||
3481 | enum { funcp = 0 }; | 3506 | enum { funcp = 0 }; |
3482 | #endif | 3507 | #endif |
3483 | char **new_env = NULL; | 3508 | char **new_env = NULL; |
3484 | char **old_env = NULL; | 3509 | struct variable *old_vars = NULL; |
3485 | 3510 | ||
3486 | if (argv[command->assignment_cnt] == NULL) { | 3511 | if (argv[command->assignment_cnt] == NULL) { |
3487 | /* Assignments, but no command */ | 3512 | /* Assignments, but no command */ |
@@ -3529,7 +3554,7 @@ static int run_pipe(struct pipe *pi) | |||
3529 | rcode = setup_redirects(command, squirrel); | 3554 | rcode = setup_redirects(command, squirrel); |
3530 | if (rcode == 0) { | 3555 | if (rcode == 0) { |
3531 | new_env = expand_assignments(argv, command->assignment_cnt); | 3556 | new_env = expand_assignments(argv, command->assignment_cnt); |
3532 | old_env = putenv_all_and_save_old(new_env); | 3557 | old_vars = set_vars_all_and_save_old(new_env); |
3533 | if (!funcp) { | 3558 | if (!funcp) { |
3534 | debug_printf_exec(": builtin '%s' '%s'...\n", | 3559 | debug_printf_exec(": builtin '%s' '%s'...\n", |
3535 | x->cmd, argv_expanded[1]); | 3560 | x->cmd, argv_expanded[1]); |
@@ -3548,11 +3573,8 @@ static int run_pipe(struct pipe *pi) | |||
3548 | clean_up_and_ret: | 3573 | clean_up_and_ret: |
3549 | #endif | 3574 | #endif |
3550 | restore_redirects(squirrel); | 3575 | restore_redirects(squirrel); |
3551 | free_strings_and_unsetenv(new_env, 1); | 3576 | free_strings_and_unset(new_env, 1); |
3552 | putenv_all(old_env); | 3577 | add_vars(old_vars); |
3553 | /* Free the pointers, but the strings themselves | ||
3554 | * are in environ now, don't use free_strings! */ | ||
3555 | free(old_env); | ||
3556 | clean_up_and_ret1: | 3578 | clean_up_and_ret1: |
3557 | free(argv_expanded); | 3579 | free(argv_expanded); |
3558 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) | 3580 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) |
@@ -3567,7 +3589,7 @@ static int run_pipe(struct pipe *pi) | |||
3567 | rcode = setup_redirects(command, squirrel); | 3589 | rcode = setup_redirects(command, squirrel); |
3568 | if (rcode == 0) { | 3590 | if (rcode == 0) { |
3569 | new_env = expand_assignments(argv, command->assignment_cnt); | 3591 | new_env = expand_assignments(argv, command->assignment_cnt); |
3570 | old_env = putenv_all_and_save_old(new_env); | 3592 | old_vars = set_vars_all_and_save_old(new_env); |
3571 | debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", | 3593 | debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", |
3572 | argv_expanded[0], argv_expanded[1]); | 3594 | argv_expanded[0], argv_expanded[1]); |
3573 | rcode = run_nofork_applet(i, argv_expanded); | 3595 | rcode = run_nofork_applet(i, argv_expanded); |
@@ -3592,7 +3614,7 @@ static int run_pipe(struct pipe *pi) | |||
3592 | #if !BB_MMU | 3614 | #if !BB_MMU |
3593 | volatile nommu_save_t nommu_save; | 3615 | volatile nommu_save_t nommu_save; |
3594 | nommu_save.new_env = NULL; | 3616 | nommu_save.new_env = NULL; |
3595 | nommu_save.old_env = NULL; | 3617 | nommu_save.old_vars = NULL; |
3596 | nommu_save.argv = NULL; | 3618 | nommu_save.argv = NULL; |
3597 | nommu_save.argv_from_re_execing = NULL; | 3619 | nommu_save.argv_from_re_execing = NULL; |
3598 | #endif | 3620 | #endif |
@@ -3665,11 +3687,8 @@ static int run_pipe(struct pipe *pi) | |||
3665 | /* Clean up after vforked child */ | 3687 | /* Clean up after vforked child */ |
3666 | free(nommu_save.argv); | 3688 | free(nommu_save.argv); |
3667 | free(nommu_save.argv_from_re_execing); | 3689 | free(nommu_save.argv_from_re_execing); |
3668 | free_strings_and_unsetenv(nommu_save.new_env, 1); | 3690 | free_strings_and_unset(nommu_save.new_env, 1); |
3669 | putenv_all(nommu_save.old_env); | 3691 | add_vars(nommu_save.old_vars); |
3670 | /* Free the pointers, but the strings themselves | ||
3671 | * are in environ now, don't use free_strings! */ | ||
3672 | free(nommu_save.old_env); | ||
3673 | #endif | 3692 | #endif |
3674 | free(argv_expanded); | 3693 | free(argv_expanded); |
3675 | argv_expanded = NULL; | 3694 | argv_expanded = NULL; |
diff --git a/shell/hush_test/hush-bugs/env_and_func.right b/shell/hush_test/hush-misc/env_and_func.right index 4a1545058..4a1545058 100644 --- a/shell/hush_test/hush-bugs/env_and_func.right +++ b/shell/hush_test/hush-misc/env_and_func.right | |||
diff --git a/shell/hush_test/hush-bugs/env_and_func.tests b/shell/hush_test/hush-misc/env_and_func.tests index d62c1af40..1d4eaf3a7 100755 --- a/shell/hush_test/hush-bugs/env_and_func.tests +++ b/shell/hush_test/hush-misc/env_and_func.tests | |||
@@ -1,5 +1,3 @@ | |||
1 | # UNFIXED BUG | ||
2 | |||
3 | var=old | 1 | var=old |
4 | f() { echo "var=$var"; } | 2 | f() { echo "var=$var"; } |
5 | var=val f | 3 | var=val f |