Subject: bin/2069: /bin/sh sometimes mis-expands variables
To: None <gnats-bugs@NetBSD.ORG>
From: Tor Egge <tegge@idt.unit.no>
List: netbsd-bugs
Date: 02/11/1996 23:48:55
>Number: 2069
>Category: bin
>Synopsis: /bin/sh sometimes mis-expands variables
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: bin-bug-people (Utility Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Feb 11 18:35:01 1996
>Last-Modified:
>Originator:
>Organization:
Norwegian University of Technology and Science
>Release: NetBSD 1.1
>Environment:
System: NetBSD ikke.idt.unit.no 1.1A NetBSD 1.1A (TEGGE) #0: Sun Feb 11 00:14:06 MET 1996 root@ikke.idt.unit.no:/usr/src/sys/arch/i386/compile/TEGGE i386
>Description:
The routine evalvar calls the routine subevalvar with a character
pointer that becomes invalid if stackblock() changes the value
inside subevalvar. This causes ksh-style variable expansion to
fail.
I discovered this when make install in /usr/src/bin/ln failed for
NetBSD-current.
>How-To-Repeat:
uudecode the following shell script, and run it. It is uuencoded
because the bug is highly dependent upon exact memory usage.
begin 755 badscript
M(R$O8FEN+W-H"F9O<B!P86=E(&EN(&QN+F-A=#$@<WEM;&EN:RYC870W.R!D
M;R`@9&ER/2]U<W(O<VAA<F4O;6%N+V-A="1[<&%G92,C*BYC871].R`@:6YS
M='!A9V4])'MD:7)]+R1[<&%G924N*GTN,#L@(&EF(%L@6"(B(#T@6"!=.R!T
M:&5N("!E8VAO(&EN<W1A;&P@+6,@+6\@8FEN("UG(&)I;B`M;2`T-#0@)'!A
M9V4@)&EN<W1P86=E.R`@96-H;R`@+6,@+6\@8FEN("UG(&)I;B`M;2`T-#0@
M)'!A9V4@)&EN<W1P86=E.R`@96QS92`@<FT@+68@)&EN<W1P86=E.R`@96-H
M;R`@)'!A9V4@7#X@)&EN<W1P86=E.R`@("1P86=E(#X@)&EN<W1P86=E.R`@
M8VAO=VX@8FEN.F)I;B`D:6YS='!A9V4[("!C:&UO9"`T-#0@)&EN<W1P86=E
-.R`@9FD@(&1O;F4*"B`D
`
end
The result is
install -c -o bin -g bin -m 444 ln.cat1 /usr/share/man/cat1/ln.0
-c -o bin -g bin -m 444 ln.cat1 /usr/share/man/cat1/ln.0
install -c -o bin -g bin -m 444 symlink.cat7 /usr/share/man/catsymlink.cat7/symlink.0
-c -o bin -g bin -m 444 symlink.cat7 /usr/share/man/catsymlink.cat7/symlink.0
while it should be
install -c -o bin -g bin -m 444 ln.cat1 /usr/share/man/cat1/ln.0
-c -o bin -g bin -m 444 ln.cat1 /usr/share/man/cat1/ln.0
install -c -o bin -g bin -m 444 symlink.cat7 /usr/share/man/cat7/symlink.0
-c -o bin -g bin -m 444 symlink.cat7 /usr/share/man/cat7/symlink.0
>Fix:
Apply this patch.
*** /usr/src/bin/sh/expand.c.orig Sun Feb 11 23:02:28 1996
--- usr/src/bin/sh/expand.c Sun Feb 11 23:07:00 1996
***************
*** 98,104 ****
STATIC void argstr __P((char *, int));
STATIC char *exptilde __P((char *, int));
STATIC void expbackq __P((union node *, int, int));
! STATIC int subevalvar __P((char *, char *, int, int, int));
STATIC char *evalvar __P((char *, int));
STATIC int varisset __P((int));
STATIC void varvalue __P((int, int, int));
--- 98,104 ----
STATIC void argstr __P((char *, int));
STATIC char *exptilde __P((char *, int));
STATIC void expbackq __P((union node *, int, int));
! STATIC int subevalvar __P((char *, char *,int, int, int, int));
STATIC char *evalvar __P((char *, int));
STATIC int varisset __P((int));
STATIC void varvalue __P((int, int, int));
***************
*** 424,432 ****
STATIC int
! subevalvar(p, str, subtype, startloc, varflags)
char *p;
char *str;
int subtype;
int startloc;
int varflags;
--- 424,433 ----
STATIC int
! subevalvar(p, str, strloc, subtype, startloc, varflags)
char *p;
char *str;
+ int strloc;
int subtype;
int startloc;
int varflags;
***************
*** 443,448 ****
--- 444,451 ----
herefd = saveherefd;
argbackq = saveargbackq;
startp = stackblock() + startloc;
+ if (!str)
+ str = stackblock() + strloc;
switch (subtype) {
case VSASSIGN:
***************
*** 633,646 ****
*/
STPUTC('\0', expdest);
pat = expdest;
! if (subevalvar(p, pat, subtype, startloc, varflags))
goto record;
break;
case VSASSIGN:
case VSQUESTION:
if (!set) {
! if (subevalvar(p, var, subtype, startloc, varflags))
goto again;
break;
}
--- 636,649 ----
*/
STPUTC('\0', expdest);
pat = expdest;
! if (subevalvar(p, NULL, pat - stackblock(), subtype, startloc, varflags))
goto record;
break;
case VSASSIGN:
case VSQUESTION:
if (!set) {
! if (subevalvar(p, var, 0, subtype, startloc, varflags))
goto again;
break;
}
>Audit-Trail:
>Unformatted: