Secure Coding mailing list archives

upwards growing stacks


From: karger at watson.ibm.com (karger at watson.ibm.com)
Date: Fri, 31 Mar 2006 12:55:32 -0500


Steve Bellovin <smb at cs.columbia.edu writes:

I've heard that claim before; I've always thought it overrated.  In an
upward-growing stack, if you overflow a parameter passed to a
subroutine it will overwrite the subroutine's return address.  Since
many buffer overflows happen as a result of library calls -- think
strcpy() or scanf() -- this can be *more* of a danger.

The real advantage on Multics was PL/I, where character strings of
declared lengths were a built-in data type.


Steve is absolutely correct.  The upwards growing stack protects a
routine against overflowing its own buffer.  If the buffer was passed
to the routine by a caller, the upwards growing stack does nothing.

However, the PL/I language does provide protection in that case.

Assume that the buffer in question is a character string.  Similar
things were done for arrays and structures.

The incoming parameter has to be declared, either with a specified
length which is known at compile time, or it must be declared as a
char(*) parameter.  If it has a specified maximum length (even if is a
varying string), the compiler knows what that length is and generates
code that either truncates or blank extends assignment statements,
as required.

If it is a char(*) parameter, then the caller is REQUIRED to pass an
argument descriptor that specifies the maximum length.  This argument
descriptor is created automatically by the compiler of the calling
routine.  The compiler generates code to use the length in the argument
descriptor to do the same truncation or blank extension as required.
The software author does not need to write anything about
argument descriptors (and indeed, cannot from PL/I).  It was all done
automatically by the Multics compilers for ALL languages, not just
PL/I.

What I described above were simple string assignment statements.  There
is also the substr() function and pseudo-op in PL/I that can specify
particular offsets within a string.  To get the offset values checked, you
had to turn on STRINGRANGE checking which would generate extra code to
do the checks.  There were probably other checks done by STRINGRANGE
that I don't remember.  (It's been a LONG time...)

I've always thought it a shame that PL/I usage has mostly died out,
although IBM still supports it for many machines.  The ANSI G subset
of PL/I was a quite reasonable language for systems programming, much
better than C, and not that much harder to compile than C.  Full PL/I
is another story.

    - Paul



Current thread: