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: