0

您好,我的一个朋友向我展示了这段代码,以说明数组/堆栈边界检查。

#include <stdio.h>

void foo() {
    unsigned long long a[1];
    a[3] -= 5;
    printf("Print me!\n");    
}

int main(){ 
    foo();
    return 0;    
}

当我运行这段代码时,它一直在打印“打印我!\n”,它只是不会停止。我已经用 MingW 64bit 编译了代码。这里发生了什么事?我想有人解释一下,为什么它一直打印文本。

4

3 回答 3

3

您通过命令损坏线程堆栈,a[3] -= 5;因为将 var 更改为超出数组范围。这种行为是完全不可预测的,并且在其他系统上可能会有所不同。我想你只是修改堆栈上的返回地址来调用 printf

如果您想了解-使用反汇编程序。

于 2012-10-13T17:57:30.157 回答
1

您正在 foo() 中更改堆栈帧之外的值。

具体来说,您从返回地址中减去 5(如果这是正常的 x86-32 调用约定)

如果 main 中的 foo() 调用被编译成类似

call ebp-126(调用短偏移)该指令长 5 个字节。

因此,返回将转到调用,而不是调用之后。并且调用将再次执行。

但是,这与代码一样具有反可移植性和未定义性,因为它取决于调用约定和编译器发出的特定指令。

于 2012-10-13T17:56:45.970 回答
0

看起来可能是堆栈缓冲区溢出

您正在引用堆栈数组中的未定义索引a。这可能会覆盖堆栈上的返回地址。

当函数returns 到main函数时,它很可能foo再次执行,因为返回地址可能被设置为- 5操作调用函数之前的值。

于 2012-10-13T17:56:03.590 回答