sh: Update associated state when restoring locals while leaving a function.
Some variables like PATH call a function when modified. Make sure to call this also when leaving a function where such a variable was made local. Make sure to restore local variables before shellparam, so getopts state is not clobbered.
This commit is contained in:
parent
21632a9bd9
commit
d42a26ab20
@ -1039,12 +1039,12 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
reffunc(cmdentry.u.func);
|
||||
savehandler = handler;
|
||||
if (setjmp(jmploc.loc)) {
|
||||
freeparam(&shellparam);
|
||||
shellparam = saveparam;
|
||||
popredir();
|
||||
unreffunc(cmdentry.u.func);
|
||||
poplocalvars();
|
||||
localvars = savelocalvars;
|
||||
freeparam(&shellparam);
|
||||
shellparam = saveparam;
|
||||
funcnest--;
|
||||
handler = savehandler;
|
||||
longjmp(handler->loc, 1);
|
||||
|
@ -111,6 +111,7 @@ FILES+= local1.0
|
||||
FILES+= local2.0
|
||||
FILES+= local3.0
|
||||
FILES+= local4.0
|
||||
FILES+= local5.0
|
||||
.if ${MK_NLS} != "no"
|
||||
FILES+= locale1.0
|
||||
.endif
|
||||
|
15
bin/sh/tests/builtins/local5.0
Normal file
15
bin/sh/tests/builtins/local5.0
Normal file
@ -0,0 +1,15 @@
|
||||
# $FreeBSD$
|
||||
|
||||
f() {
|
||||
local PATH IFS elem
|
||||
IFS=:
|
||||
for elem in ''$PATH''; do
|
||||
PATH=/var/empty/$elem:$PATH
|
||||
done
|
||||
ls -d / >/dev/null
|
||||
}
|
||||
|
||||
p1=$(command -v ls)
|
||||
f
|
||||
p2=$(command -v ls)
|
||||
[ "$p1" = "$p2" ]
|
11
bin/sh/var.c
11
bin/sh/var.c
@ -791,6 +791,7 @@ poplocalvars(void)
|
||||
{
|
||||
struct localvar *lvp;
|
||||
struct var *vp;
|
||||
int islocalevar;
|
||||
|
||||
INTOFF;
|
||||
while ((lvp = localvars) != NULL) {
|
||||
@ -803,10 +804,20 @@ poplocalvars(void)
|
||||
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
||||
(void)unsetvar(vp->text);
|
||||
} else {
|
||||
islocalevar = (vp->flags | lvp->flags) & VEXPORT &&
|
||||
localevar(lvp->text);
|
||||
if ((vp->flags & VTEXTFIXED) == 0)
|
||||
ckfree(vp->text);
|
||||
vp->flags = lvp->flags;
|
||||
vp->text = lvp->text;
|
||||
if (vp->func)
|
||||
(*vp->func)(vp->text + vp->name_len + 1);
|
||||
if (islocalevar) {
|
||||
change_env(vp->text, vp->flags & VEXPORT &&
|
||||
(vp->flags & VUNSET) == 0);
|
||||
setlocale(LC_ALL, "");
|
||||
updatecharset();
|
||||
}
|
||||
}
|
||||
ckfree(lvp);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user