diff options
author | Ron Yorston <rmy@pobox.com> | 2018-03-31 10:23:59 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-03-31 10:23:59 +0100 |
commit | ada909acfa49fa59bbd8005e5b118c32447dfad0 (patch) | |
tree | 10b0e9d7ce7d5d6e1405d3fac4bf9307882ee799 | |
parent | e2f7bd0469c8751d9f37d493d395180a61286e94 (diff) | |
download | busybox-w32-ada909acfa49fa59bbd8005e5b118c32447dfad0.tar.gz busybox-w32-ada909acfa49fa59bbd8005e5b118c32447dfad0.tar.bz2 busybox-w32-ada909acfa49fa59bbd8005e5b118c32447dfad0.zip |
ash: revise handling of builtin environment variables during fork
Commit db03ff5ea made some improvements to the handling of builtin
environment variables during forkshell. However, more can be done.
Currently the calculated size of varinit doesn't match what's actually
copied. It overestimates the amount of string space and the number
of pointers. The text of each builtin environment variable is also
copied twice: once as part of vartab and again from varinit.
Remove the code to copy varinit via the forkshell block. Instead
use information from vartab and varinit_data to reinitialise varinit
and fix the links in vartab.
In addition, ensure that the LINENO variable is properly initialised
in the child.
-rw-r--r-- | shell/ash.c | 56 |
1 files changed, 24 insertions, 32 deletions
diff --git a/shell/ash.c b/shell/ash.c index 2d51b48f9..57f87f0e1 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -14946,27 +14946,31 @@ forkshell_child(struct forkshell *fs) | |||
14946 | } | 14946 | } |
14947 | 14947 | ||
14948 | /* | 14948 | /* |
14949 | * Reset the pointers to the builtin environment variables in the hash | 14949 | * Reinitialise the builtin environment variables in varinit. Their |
14950 | * table to point to varinit rather than the bogus copy created during | 14950 | * current settings have been copied from the parent in vartab. Look |
14951 | * forkshell_prepare. | 14951 | * these up using the names from varinit_data, copy the details from |
14952 | * vartab to varinit and replace the old copy in vartab with the new | ||
14953 | * one in varinit. | ||
14954 | * | ||
14955 | * Also reinitialise the function pointers and line number variable. | ||
14952 | */ | 14956 | */ |
14953 | static void | 14957 | static void |
14954 | reinitvar(void) | 14958 | reinitvar(void) |
14955 | { | 14959 | { |
14956 | struct var *vp; | 14960 | int i; |
14957 | struct var *end; | 14961 | const char *name; |
14958 | struct var **vpp; | 14962 | struct var **vpp, **old; |
14959 | struct var **old; | ||
14960 | 14963 | ||
14961 | vp = varinit; | 14964 | for (i=0; i<ARRAY_SIZE(varinit); ++i) { |
14962 | end = vp + ARRAY_SIZE(varinit); | 14965 | name = varinit_data[i].var_text ? varinit_data[i].var_text : "LINENO="; |
14963 | do { | 14966 | vpp = hashvar(name); |
14964 | vpp = hashvar(vp->var_text); | 14967 | if ( (old=findvar(vpp, name)) != NULL ) { |
14965 | if ( (old=findvar(vpp, vp->var_text)) != NULL ) { | 14968 | varinit[i] = **old; |
14966 | vp->next = (*old)->next; | 14969 | *old = varinit+i; |
14967 | *old = vp; | ||
14968 | } | 14970 | } |
14969 | } while (++vp < end); | 14971 | varinit[i].var_func = varinit_data[i].var_func; |
14972 | } | ||
14973 | vlineno.var_text = linenovar; | ||
14970 | } | 14974 | } |
14971 | 14975 | ||
14972 | /* FIXME: should consider running forkparent() and forkchild() */ | 14976 | /* FIXME: should consider running forkparent() and forkchild() */ |
@@ -15049,10 +15053,6 @@ SLIST_SIZE_END() | |||
15049 | SLIST_COPY_BEGIN(var_copy,struct var) | 15053 | SLIST_COPY_BEGIN(var_copy,struct var) |
15050 | (*vpp)->var_text = nodeckstrdup(vp->var_text); | 15054 | (*vpp)->var_text = nodeckstrdup(vp->var_text); |
15051 | (*vpp)->flags = vp->flags; | 15055 | (*vpp)->flags = vp->flags; |
15052 | /* | ||
15053 | * The only place that can set struct var#func is varinit[], | ||
15054 | * which will be fixed by forkshell_init() | ||
15055 | */ | ||
15056 | (*vpp)->var_func = NULL; | 15056 | (*vpp)->var_func = NULL; |
15057 | SAVE_PTR((*vpp)->var_text); | 15057 | SAVE_PTR((*vpp)->var_text); |
15058 | SLIST_COPY_END() | 15058 | SLIST_COPY_END() |
@@ -15230,12 +15230,12 @@ globals_var_size(struct globals_var *gvp) | |||
15230 | redirtab_size(gvp->redirlist); | 15230 | redirtab_size(gvp->redirlist); |
15231 | for (i = 0; i < VTABSIZE; i++) | 15231 | for (i = 0; i < VTABSIZE; i++) |
15232 | var_size(gvp->vartab[i]); | 15232 | var_size(gvp->vartab[i]); |
15233 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) | 15233 | nodeptrsize += 2 + VTABSIZE; /* gvp->redirlist, gvp->shellparam.p, vartab */ |
15234 | var_size(gvp->varinit+i); | ||
15235 | nodeptrsize += 2 + VTABSIZE; /* gvp->redirlist, gvp->shellparam.p, vartab */ | ||
15236 | } | 15234 | } |
15237 | 15235 | ||
15238 | #undef preverrout_fd | 15236 | #undef preverrout_fd |
15237 | #undef lineno | ||
15238 | #undef linenovar | ||
15239 | static struct globals_var * | 15239 | static struct globals_var * |
15240 | globals_var_copy(struct globals_var *gvp) | 15240 | globals_var_copy(struct globals_var *gvp) |
15241 | { | 15241 | { |
@@ -15260,14 +15260,8 @@ globals_var_copy(struct globals_var *gvp) | |||
15260 | SAVE_PTR(new->vartab[i]); | 15260 | SAVE_PTR(new->vartab[i]); |
15261 | } | 15261 | } |
15262 | 15262 | ||
15263 | /* Can't use var_copy because varinit is already allocated */ | 15263 | new->lineno = gvp->lineno; |
15264 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { | 15264 | strcpy(new->linenovar, gvp->linenovar); |
15265 | new->varinit[i].next = NULL; | ||
15266 | new->varinit[i].var_text = nodeckstrdup(gvp->varinit[i].var_text); | ||
15267 | SAVE_PTR(new->varinit[i].var_text); | ||
15268 | new->varinit[i].flags = gvp->varinit[i].flags; | ||
15269 | new->varinit[i].var_func = gvp->varinit[i].var_func; | ||
15270 | } | ||
15271 | return new; | 15265 | return new; |
15272 | } | 15266 | } |
15273 | 15267 | ||
@@ -15425,8 +15419,6 @@ forkshell_init(const char *idstr) | |||
15425 | } | 15419 | } |
15426 | 15420 | ||
15427 | /* Now fix up stuff that can't be transferred */ | 15421 | /* Now fix up stuff that can't be transferred */ |
15428 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) | ||
15429 | fs->gvp->varinit[i].var_func = varinit_data[i].var_func; | ||
15430 | for (i = 0; i < CMDTABLESIZE; i++) { | 15422 | for (i = 0; i < CMDTABLESIZE; i++) { |
15431 | struct tblentry *e = fs->cmdtable[i]; | 15423 | struct tblentry *e = fs->cmdtable[i]; |
15432 | while (e) { | 15424 | while (e) { |