Subject: Two bugs in /bin/sh ...

From: Andrew Cagney <[email-masked]>

Hello,

At the end of this mail is a patch to two somewhat obscure bugs in
/bin/sh in the 1st Aug beta.

	o	When expanding ${PWD=`pwd`} where
		PWD is not defined.  It does an IFS split on
		incorrect data.  That is

			${PWD=`pwd`}
		is	${PWD=/some/directory}
			${PWD}

		At this point PWD is given the value
		/some/directory, and the value is discarded
		from a string stack.  When this is done, the
		code fails to also remove the marker for the
		*removed* string to be processed for IFS's.

		Fortunatly, the next thing that is done is that
		the string is put back (expanding ${PWD}).
		so the mistake isn't noticed.

	o	(Down right obscure)

		A macro is called with an expression as its first
		argument.  The expression is then evaluated twice
		within the macro.  Unfortunatly, the first evaluation
		has the side effect of changing the expressions value.

		The net result is that the string heap becomes corrupted

		To reproduce this, run the configure script in gas-4.13
		(The best I could do with the script was get it down to
		~350 lines).

				enjoy, Andrew

~v

*** SRC/expand.c	Sun Jun 12 03:01:31 1994
--- expand.c	Fri Sep  9 06:36:07 1994
***************
*** 488,502 ****
  			char *startp;
  			int saveherefd = herefd;
  			struct nodelist *saveargbackq = argbackq;
  			herefd = -1;
  			argstr(p, 0);
  			STACKSTRNUL(expdest);
  			herefd = saveherefd;
  			argbackq = saveargbackq;
  			startp = stackblock() + startloc;
  			if (subtype == VSASSIGN) {
  				setvar(var, startp, 0);
! 				STADJUST(startp - expdest, expdest);
  				varflags &=~ VSNUL;
  				goto again;
  			}
--- 488,507 ----
  			char *startp;
  			int saveherefd = herefd;
  			struct nodelist *saveargbackq = argbackq;
+ 			struct ifsregion saveifs = ifsfirst;
+ 			struct ifsregion *savelastp = ifslastp;
  			herefd = -1;
  			argstr(p, 0);
  			STACKSTRNUL(expdest);
  			herefd = saveherefd;
  			argbackq = saveargbackq;
+ 			ifsfirst = saveifs;
+ 			ifslastp = savelastp;
  			startp = stackblock() + startloc;
  			if (subtype == VSASSIGN) {
+ 				int slen = startp - expdest;
  				setvar(var, startp, 0);
! 				STADJUST(slen, expdest);
  				varflags &=~ VSNUL;
  				goto again;
  			}