aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-03-31 10:23:59 +0100
committerRon Yorston <rmy@pobox.com>2018-03-31 10:23:59 +0100
commitada909acfa49fa59bbd8005e5b118c32447dfad0 (patch)
tree10b0e9d7ce7d5d6e1405d3fac4bf9307882ee799
parente2f7bd0469c8751d9f37d493d395180a61286e94 (diff)
downloadbusybox-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.c56
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 */
14953static void 14957static void
14954reinitvar(void) 14958reinitvar(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()
15049SLIST_COPY_BEGIN(var_copy,struct var) 15053SLIST_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;
15057SAVE_PTR((*vpp)->var_text); 15057SAVE_PTR((*vpp)->var_text);
15058SLIST_COPY_END() 15058SLIST_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
15239static struct globals_var * 15239static struct globals_var *
15240globals_var_copy(struct globals_var *gvp) 15240globals_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) {