Subject: bin/2070: more bug about ksh-style variable substitution in /bin/sh
To: None <gnats-bugs@NetBSD.ORG>
From: None <enami@ba2.so-net.or.jp>
List: netbsd-bugs
Date: 02/12/1996 17:04:35
>Number:         2070
>Category:       bin
>Synopsis:       more bug about ksh-style variable substitution in /bin/sh
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 12 04:20:01 1996
>Last-Modified:
>Originator:     enami tsugutomo
>Organization:
	one of hacker, in japan.
>Release:        NetBSD-current around Feb 10
>Environment:
System: NetBSD pavlov 1.1A NetBSD 1.1A (PAVLOV) #3: Mon Feb 12 00:16:15 JST 1996 enami@pavlov:/c/src/sys/arch/i386/compile/PAVLOV i386


>Description:
	In addtion to PR#2069, there is more problem about ksh-style
	variable substitution in /bin/sh.
>How-To-Repeat:
	In my environment, make -DMANZ install in share/man/man7 gives
	following incorrect result.

gzip -cf ascii.cat7 > /usr/share/man/cat7/ascii.0at7
gzip -cf environ.cat7 > /usr/share/man/cat7/environ.0.gz
gzip -cf hier.cat7 > /usr/share/man/cat7/hier.0.t7
gzip -cf hostname.cat7 > /usr/share/man/cat7/hostname.0.gz
gzip -cf intro.cat7 > /usr/share/man/cat7/intro.0at7
gzip -cf mailaddr.cat7 > /usr/share/man/cat7/mailaddr.0.gz
gzip -cf mdoc.cat7 > /usr/share/man/cat7/mdoc.0.t7

>Fix:
	The reason is that there is a place where expdest is set directly.
	As a result, expdest doesn't sync with sstrnleft, realloc'ed even
	if there is room, expdest is set according to sstrnleft, and it
	means that it skip the room.

	To fix the problem, use STADJUST macro to set expdest.
	For example, use
		amount = new_expdest - expdest;
		STADJUST(amount, expdest);
	instead of
		expdest = new_expdest;
	Note that we can't write as
		STADJUST(new_expdest - expdest, expdest);
	because of STADJUST definition; it modifies expdest first.

	Here is a patch including patch in PR#2069
enami.

*** expand.c	1996/02/12 04:43:21	1.1
--- expand.c	1996/02/12 07:44:43
***************
*** 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,453 ****
  
  
  STATIC int
! subevalvar(p, str, subtype, startloc, varflags)
  	char *p;
  	char *str;
  	int subtype;
  	int startloc;
  	int varflags;
  {
- 
  	char *startp;
  	char *loc;
  	int c = 0;
  	int saveherefd = herefd;
  	struct nodelist *saveargbackq = argbackq;
  	herefd = -1;
  	argstr(p, 0);
  	STACKSTRNUL(expdest);
  	herefd = saveherefd;
  	argbackq = saveargbackq;
  	startp = stackblock() + startloc;
  
  	switch (subtype) {
  	case VSASSIGN:
  		setvar(str, startp, 0);
! 		STADJUST(startp - expdest, expdest);
  		varflags &= ~VSNUL;
  		if (c != 0)
  			*loc = c;
--- 424,458 ----
  
  
  STATIC int
! subevalvar(p, str, strloc, subtype, startloc, varflags)
  	char *p;
  	char *str;
+ 	int strloc;
  	int subtype;
  	int startloc;
  	int varflags;
  {
  	char *startp;
  	char *loc;
  	int c = 0;
  	int saveherefd = herefd;
  	struct nodelist *saveargbackq = argbackq;
+ 	int amount;
+ 
  	herefd = -1;
  	argstr(p, 0);
  	STACKSTRNUL(expdest);
  	herefd = saveherefd;
  	argbackq = saveargbackq;
  	startp = stackblock() + startloc;
+ 	if (str == NULL)
+ 	    str = stackblock() + strloc;
  
  	switch (subtype) {
  	case VSASSIGN:
  		setvar(str, startp, 0);
! 		amount = startp - expdest;
! 		STADJUST(amount, expdest);
  		varflags &= ~VSNUL;
  		if (c != 0)
  			*loc = c;
***************
*** 490,496 ****
  	case VSTRIMRIGHT:
  		for (loc = str - 1; loc >= startp; loc--) {
  			if (patmatch(str, loc)) {
! 				expdest = loc;
  				return 1;
  			}
  		}
--- 495,502 ----
  	case VSTRIMRIGHT:
  		for (loc = str - 1; loc >= startp; loc--) {
  			if (patmatch(str, loc)) {
! 				amount = loc - expdest;
! 				STADJUST(amount, expdest);
  				return 1;
  			}
  		}
***************
*** 499,505 ****
  	case VSTRIMRIGHTMAX:
  		for (loc = startp; loc < str - 1; loc++) {
  			if (patmatch(str, loc)) {
! 				expdest = loc;
  				return 1;
  			}
  		}
--- 505,512 ----
  	case VSTRIMRIGHTMAX:
  		for (loc = startp; loc < str - 1; loc++) {
  			if (patmatch(str, loc)) {
! 				amount = loc - expdest;
! 				STADJUST(amount, expdest);
  				return 1;
  			}
  		}
***************
*** 511,517 ****
  	}
  
  recordleft:
! 	expdest = (str - 1) - (loc - startp);
  	while (loc != str - 1)
  		*startp++ = *loc++;
  	return 1;
--- 518,525 ----
  	}
  
  recordleft:
! 	amount = ((str - 1) - (loc - startp)) - expdest;
! 	STADJUST(amount, expdest);
  	while (loc != str - 1)
  		*startp++ = *loc++;
  	return 1;
***************
*** 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;
  		}
--- 641,655 ----
  		 */
  		STPUTC('\0', expdest);
  		pat = expdest;
! 		if (subevalvar(p, NULL, expdest - 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: