[net.unix-wizards] Bourne shell's wacky memory allocation

guy@sun.uucp (Guy Harris) (10/27/85)

> This is real easy to fix.

I know - I had to fix it here; I did so by doing the "setbrk" directly
instead of faking a SIGSEGV.  (The code in question - added to the shell -
was allocating some BMF structures, and I didn't feel like having the shell
keep bumping its data space up until it got big enough).

Your line numbers may differ.  This is for the S5R2 shell.  It's probably
similar for others.

*** /tmp/da6483	Sat Oct 26 15:17:15 1985
--- blok.c	Thu Oct 10 18:20:49 1985
***************
*** 87,92
  	reqd &= ~(brkincr - 1);
  	blokp = bloktop;
  	bloktop = bloktop->word = (struct blk *)(Rcheat(bloktop) + reqd);
  	bloktop->word = (struct blk *)(brkbegin + 1);
  	{
  		register char *stakadr = (char *)(bloktop + 2);

--- 87,95 -----
  	reqd &= ~(brkincr - 1);
  	blokp = bloktop;
  	bloktop = bloktop->word = (struct blk *)(Rcheat(bloktop) + reqd);
+ 	reqd = (char *)(&bloktop->word) - brkend;
+ 	if (reqd > 0 && setbrk(reqd) == (char *)-1)
+ 		error(nospace);
  	bloktop->word = (struct blk *)(brkbegin + 1);
  	{
  		register char *stakadr = (char *)(bloktop + 2);

The reason why this causes problems on 68010s is not that you can't continue
from an instruction.  The problem is that you can't do so *from user mode*
without kernel hacks.  In order to continue the instruction, the "stack
puke" (as Henry Spencer described it) must be on the stack when the RTE is
done.  The RTE must be done from the kernel, since it's privileged.  In some
UNIXes, returning from a signal doesn't involve the kernel (you can do an
RTR to reload the condition codes) - you're out of luck there.  In others
(like 4.2BSD, which has to reenable the signal in question) returning from a
signal requires you to pass through the kernel.  However, the bus error
frame isn't likely to be on the kernel stack anymore.  You'd have to
squirrel it away somewhere - somewhere inaccessible to the user, because I
don't think Motorola tells you 1) that it won't kill the system if you RTE
with arbitrary bits or 2) how to make sure that a bus error frame is safe.
Sun UNIX doesn't do this, and other 68010 UNIXes may not either.

	Guy Harris

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (10/28/85)

It appears that Guy's fix will make SIGSEGV available for general use
rather than reserved to the shell internals.  That would be nice.

guy@sun.uucp (Guy Harris) (11/09/85)

> It appears that Guy's fix will make SIGSEGV available for general use
> rather than reserved to the shell internals.  That would be nice.

Don't count your blessings until they've hatched, or something like that.
It doesn't make it available for general use, trust me.  You also have to
catch *all* the places where Bourne uses SIGSEGV to catch attempts to use
unallocated portions of the "stack" (temporary string space and the like is
allocated on a "stack" which consists mostly of the growing end of the data
space, although it's intermixed with blocks from the heap).  I got bit by
that a couple of days ago, and found *every* place where the "pushstak"
macro was used and added a test before it; if the place where the character
is to be "pushed" doesn't exist, it grows the data space.  I don't claim to
have caught every place; I want to beat on it a while, and then build a
version of the shell which *does* make SIGSEGV available for "general" use
(i.e., the shell will drop core on a SIGSEGV like it's supposed to) and try
it for a while.

It was a clever idea, my hat's off to Bourne, but I still want to get the
vanity plate SIGSEGV for him and weld it to his car, if he's got one.

	Guy Harris