sh: Ensure OPTIND=1 in subshell without forking does not affect outer env.
Command substitutions containing a single simple command and here-document expansion are performed in a subshell environment, but may not fork. Any modified state of the shell environment should be restored afterward. The state that OPTIND=1 had been done was not saved and restored here. Note that the other parts of shellparam need not be saved and restored, since they are not modified in these situations (a fork is done before such modifications).
This commit is contained in:
parent
f5b4d34104
commit
adba77a62e
@ -496,10 +496,12 @@ exphere(union node *redir, struct arglist *fn)
|
||||
struct jmploc *savehandler;
|
||||
struct localvar *savelocalvars;
|
||||
int need_longjmp = 0;
|
||||
unsigned char saveoptreset;
|
||||
|
||||
redir->nhere.expdoc = "";
|
||||
savelocalvars = localvars;
|
||||
localvars = NULL;
|
||||
saveoptreset = shellparam.reset;
|
||||
forcelocal++;
|
||||
savehandler = handler;
|
||||
if (setjmp(jmploc.loc))
|
||||
@ -514,6 +516,7 @@ exphere(union node *redir, struct arglist *fn)
|
||||
forcelocal--;
|
||||
poplocalvars();
|
||||
localvars = savelocalvars;
|
||||
shellparam.reset = saveoptreset;
|
||||
if (need_longjmp)
|
||||
longjmp(handler->loc, 1);
|
||||
INTON;
|
||||
@ -647,6 +650,7 @@ evalbackcmd(union node *n, struct backcmd *result)
|
||||
struct jmploc jmploc;
|
||||
struct jmploc *savehandler;
|
||||
struct localvar *savelocalvars;
|
||||
unsigned char saveoptreset;
|
||||
|
||||
result->fd = -1;
|
||||
result->buf = NULL;
|
||||
@ -661,6 +665,7 @@ evalbackcmd(union node *n, struct backcmd *result)
|
||||
if (is_valid_fast_cmdsubst(n)) {
|
||||
savelocalvars = localvars;
|
||||
localvars = NULL;
|
||||
saveoptreset = shellparam.reset;
|
||||
forcelocal++;
|
||||
savehandler = handler;
|
||||
if (setjmp(jmploc.loc)) {
|
||||
@ -671,6 +676,7 @@ evalbackcmd(union node *n, struct backcmd *result)
|
||||
forcelocal--;
|
||||
poplocalvars();
|
||||
localvars = savelocalvars;
|
||||
shellparam.reset = saveoptreset;
|
||||
longjmp(handler->loc, 1);
|
||||
}
|
||||
} else {
|
||||
@ -681,6 +687,7 @@ evalbackcmd(union node *n, struct backcmd *result)
|
||||
forcelocal--;
|
||||
poplocalvars();
|
||||
localvars = savelocalvars;
|
||||
shellparam.reset = saveoptreset;
|
||||
} else {
|
||||
if (pipe(pip) < 0)
|
||||
error("Pipe call failed: %s", strerror(errno));
|
||||
|
@ -95,6 +95,7 @@ FILES+= getopts6.0
|
||||
FILES+= getopts7.0
|
||||
FILES+= getopts8.0 getopts8.0.stdout
|
||||
FILES+= getopts9.0 getopts9.0.stdout
|
||||
FILES+= getopts10.0
|
||||
FILES+= hash1.0 hash1.0.stdout
|
||||
FILES+= hash2.0 hash2.0.stdout
|
||||
FILES+= hash3.0 hash3.0.stdout
|
||||
|
11
bin/sh/tests/builtins/getopts10.0
Normal file
11
bin/sh/tests/builtins/getopts10.0
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
|
||||
set -- -x arg
|
||||
opt=not
|
||||
getopts x opt
|
||||
r1=$? OPTIND1=$OPTIND opt1=$opt
|
||||
: $(: $((OPTIND = 1)))
|
||||
getopts x opt
|
||||
r2=$? OPTIND2=$OPTIND
|
||||
[ "$r1" = 0 ] && [ "$OPTIND1" = 2 ] && [ "$opt1" = x ] && [ "$r2" != 0 ] &&
|
||||
[ "$OPTIND2" = 2 ]
|
Loading…
Reference in New Issue
Block a user