Reputation: 101
While executing the following program in Visual Studio 2012 Console App:
#include <stdio.h>
int main() {
int integer1, integer2, sum;
char str[5];
scanf("%s",str); /* Try to enter 10 chars */
printf("%s\n",str);
printf( "Enter first integer\n" );
scanf( "%d", &integer1 );
printf( "Enter second integer\n" );
scanf( "%d", &integer2 );
sum = integer1 + integer2;
printf( "Sum = %d\n", sum );
return 0;
}
It throws an exception "StackOverFlow" and this is obvious because of the statement:
scanf("%s",str); /* Try to enter 10 chars */
My question is: Why does the program continue the execution (by printing the str string, asking for entering the 2 integers, sum them and print the result also) even though the exception should have happened earlier?
Upvotes: 2
Views: 187
Reputation: 11582
The stack grows down, from high addresses to lower addresses. A CPU register, the stack pointer keeps track of the top of stack - which is in reality at the lowest address, because the stack grows towards lower addresses. The compiler looks at your function (main in this case) and looks to see how much automatic storage it needs, that is, storage for local variables. It generates code to decrement that stack pointer by the amount of local storage needed by your function. When the function gets called the caller pushes on the stack the return address (decrementing the stack pointer) and then branches to the called function, which in turn decrements the stack pointer (creating a stack frame) to make room for local variables.
If a program overflows the local variables (as yours did) it is likely to trash the return address. Since the stack grew down towards lower addresses, writing beyond the stack frame (towards higher addresses) will overwrite older stack frames (your caller, and the caller's caller, etc).
Although main() is the first function to be called in your program, there is already an active stack frame, corresponding to main()'s caller, which is the runtime environment.
Any side effects of trashing the stack (like overwriting the return address) won't be noticed until your function, main() in this case, tries to return. What happens then is anyone's guess. If the return address was overwritten with a value that points to a location on the stack, the CPU will branch there, this is a classic exploit by malicious code that takes advantage of buffer overflows with buffers allocated on the stack.
These links are helpful in understanding stack based buffer overflow:
http://www.tenouk.com/Bufferoverflowc/Bufferoverflow3.html http://en.wikipedia.org/wiki/Format_string_attack
Recent microprocessors provide a security feature that prevents execution of data, the CPU would raise an exception as soon as your program attempts to return to a corrupted address that points to data (like the stack).
http://en.wikipedia.org/wiki/NX_bit
Upvotes: 4
Reputation: 328840
In C, code can't throw exceptions. Also, scanf()
doesn't check the stack.
What probably happens is that Visual Studio creates the environment for your program, including setting up the stack. While it does that, it fills the stack with a pattern.
When main()
returns, the pattern is checked. Only at that time, the C runtime will notice that you trashed the stack.
Conclusion: Never use the unsafe versions of scanf()
and sprintf()
. The runtime might catch the error but it will do it too late and even when you get an error message, that won't help you one bit to find out when it happened.
Upvotes: 1
Reputation: 15055
Because C doesn't check everything (anything?). Your long string has scribbled on the stack, which when the function returns the stack corruption is noticed.
It's worth noting that safe versions of scanf
type functions should always be used.
Upvotes: 1