开发者

Canonical example of stack destruction in a C program

开发者 https://www.devze.com 2023-01-19 12:01 出处:网络
could someone please teach me a common exa开发者_如何学编程mple whereby (!) you destroy the stack in a C program? I use GCC, in Ubuntu.

could someone please teach me a common exa开发者_如何学编程mple whereby (!) you destroy the stack in a C program? I use GCC, in Ubuntu. Thanks.


It depends on what you mean by "destroy the stack", but this is a common error that will generally cause corruption of vital stack-resident data:

void dumb()
{
    char small[2];
    strcpy(small, "too long to fit"); // Writes past the end of "small", overwriting vital information
}

This is a common source of security holes. It can potentially be used to hijack the instruction pointer, enabling malicious code to execute. See buffer overflow.

Another mistake that might be described as "destroying the stack" is the case of infinite recursion (scroll down on that page):

int add(int n)
{
    return n + add(n + 1);
}

Which, as it lacks an exit condition, will push so many frames onto the stack that it eventually gets "full". (Unless the compiler can apply tail-call optimization; see below)

Both of these examples compile without as much as a warning using GCC 4.4.3.


Note: As Billy ONeal pointed out below, the behavior of these examples is specific to x86, not C as a language, and may vary from one compiler to another. That is not to say that they don't demonstrate how you can break the stack in a particular (and extremely common) implementation of C.


Here are a few more examples where the stack can get trashed.

char* foo()
{
    char str[256];
    return str;
}

void bar()
{
    char* str = foo();
    strcpy(str, "Holy sweet Moses! I blew my stack!!");
}

Or,

void foo()
{
    char* str; // uninitialized; has garbage value
    strcpy(str, "Holy sweet Moses! I blew my stack!!");
    // well, could be anything you are trashing
}

void foo()
{
    int* ptr; // uninitialized; has garbage value
    *ptr = "0xDEADBEEF";
    // well, could be anything you are trashing
}


You can't, at least, not according to the C standard. You might be able to use inline assembler features of GCC to mess with the stack pointer though.

EDIT: I suppose calling exit, abort, or terminate (terminate is in C++ only) would result in destruction of the stack :P


I'm not sure exactly what you mean, but whenever you exit a function the "stack" for that function is destroyed. For example:

void foo(void) {
    // a, b and c are "allocated" on the stack here
    int a, b, c;

}    // a, b and c are destroyed here

In reality the stack is never destroyed in the way you might be thinking. There is a pointer to the top of the stack and functions reference positions relative the current top of stack. When a function exits the TOS pointer is decremented by a certain amount, but no actual destruction takes place. So you could theoretically still access the values from the function after it exits, although that would be a bad idea.

You might want to take a look at these:

How Does The Function Call Stack Work?

Calling Conventions in C and C++

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号