This might be a stupid question but I was wondering what if the array was filled with values in a way of it grows in the direction of the stack (so in case of the array being the only one local variable such that the first element of the array is adressed one byte after the stackframe pointer/base pointer, the second element adressed two bytes after stackframe pointer/base pointer, ...), wouldn't it make stack overflow in C much safer since the return adress cannot be overwritten that easy (the array would have to fill nearly the entire RAM and thus the program would crash instead of execute some malicious code)?
The stack is used for dynamic memory allocation, and local variables are stored at the top of the stack in a stack frame. A frame pointer is used to refer to local variables in the stack frame.
Arrays are allocated as a single chunk of memory. Growing an array is problematic because the only way to do it properly is to grow it at the end. For a growth of size N there must be at least N free bytes at the end of the array before the next allocated address.
There is still some reason to save EBP on entry to a procedure/function though: unless the stack gets corrupted, it's really easy to walk. EBP points to the previous value of EBP, which points to the previous value, and so on all the way down the stack.
You can't do this with a stack that grows down without completely swapping the addressing model for all arrays. That's a viable implementation choice, but not compatible with existing ABIs.
What you have noticed is that, in some ways, having a stack that grows up (where up is the direction of positive array index) is in some ways safer than having a stack that grows down. However, it's not all that much safer. Consider what happens when you pass the address of an array with automatic storage to another function. The callee will appear higher on the stack than the array, so any overflow of the array will overflow into the callee's stack frame, possibly including its return address. For example:
void foo()
{
char s[4];
strcpy(s, "hello world");
}
When strcpy
returns, its return address may have been clobbered by storing past the end of the array whose address was passed to it.
"The direction of the stack" is a function of the implementation, not the language - the language specification doesn't even assume the presence of a stack.
Array indexing works by adding a non-negative offset to a base address and dereferencing the result - arrays must always grow "up" towards increasing addresses, irrespective of the stack growth direction.
The only thing that will truly make array operations safe(r) is for the C language specification to require bounds checking on all array accesses and to throw an exception on an out-of-bounds access. Of course, the C language specification would also have to add structured exception handling as well (the current signal-handling method would be woefully inadequate).
Such an addition is...unlikely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With