As for buffer
overruns, the point there is that a buffer overrun
clobbers memory addressed higher than the buffer. If the stack
grows down, this can overwrite stack frames and/or callers' locals.
If the stack grows up, all it can overwrite is locals for the
current frame and unused stack space.
If the stack is in its own segment, you get
to use the segment
protection hardware to catch overruns.
That doesn't help when (a) the stack grows downward, (b) all stack
frames are in the same segment, and (c) function-local arrays are on
the stack. Running off the end of the buffer still trashes the memory
following, which includes stack frames and calling routines' locals.
All the segment protection does is prevent you from running off the
stack into non-stack memory, which is not how typical buffer overruns
work.
To stop that, you'd have to either (a) put each stack frame in its own
segment (which means a _lot_ of segments, potentially) or (b) adjust
the segment limits with each call/return (possible, but makes it
difficult to work with pointers to variables in the stack frames of
calling routines); (b) also requires keeping the stack frame outside
the segment or below the locals.
It would help to have two stacks, one for locals and one for stack
frames, but buffer overruns could still scribble on calling routines'
locals with a downward-growing stack. Not as bad as scribbling on the
stack frame, certainly, but still not good.
/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML mouse at
rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B