为什么缓冲区溢出会在访问整数时导致分段错误?

时间:2009-12-03 23:15:08

标签: c++ c segmentation-fault buffer-overflow

在从函数A()调用函数B()期间,B()分配一个100-char数组并多次填充,包括一次使用101个字符的字符串,一次使用110个字符的字符串。这是一个明显的错误。

稍后,函数A()尝试访问完全不相关的int变量i,并发生分段错误。

我理解为什么会发生缓冲区溢出,但为什么在访问此整数时会出现分段错误?为什么我不简单地获取垃圾数据?

5 个答案:

答案 0 :(得分:14)

缓冲区溢出可能会破坏堆栈上先前保存的帧指针版本。 当函数返回时,这个损坏的版本被加载到帧指针寄存器中,从而导致你描述的行为。

Wikipedia's page包含数字和定义。

答案 1 :(得分:5)

A()调用B()时,B的前导码指令保存A的帧指针 - 堆栈中A保持局部变量的位置,然后用B自己的帧指针替换它。它看起来像这样:

Stack Frame

当B超出其局部变量时,它会混淆将重新加载到帧指针中的值。这是垃圾作为帧指针值,因此所有A的局部变量都被删除。更糟糕的是,未来对局部变量的写入会混淆属于其他人的记忆。

答案 2 :(得分:3)

你描述中最可能的解释是B中的溢出会破坏堆栈上保存的帧指针。因此,在B返回后,A在其帧指针中有垃圾,并在尝试访问局部变量时崩溃。

答案 3 :(得分:0)

如果你通过指针访问我,那么问题是指针是垃圾。

答案 4 :(得分:0)

重要的是要记住你为nul终止字符分配了足够的内存和一个(Astute读者会指出这个nul,主要是因为有一个原因 - 一个'l'是'\0' [感谢Software Monkey指出错误!],带有两个'l'的null是一个指向什么都没有的指针。

这是一个如何发生seg故障的例子

int main(int argc, char **argv){
    int *x = NULL;
    *x = 5;
    // boom
}

由于x是一个指针并设置为null,我们尝试取消引用指针并为其赋值。保证生成分段错误的方法。

有一个老技巧可以实际捕获seg错误并获得堆栈跟踪,在unix环境中更常见,通过设置信号处理程序来捕获SIGSEGV,并在信号处理程序中调用类似的进程这样:

char buf[250];
buf[0] = '\0';
sprintf(buf, "gdb -a %d | where > mysegfault.txt", getpid());
system(buf);

这会附加当前正在执行的C程序并向调试器发送并附加到它上面,where部分显示导致seg错误并将输出重定向到a的违规行的堆栈跟踪文件在当前目录中。

注意:这是实现定义的,取决于安装,在AIX下,gnu调试器存在,因此这将起作用,您的里程可能会有所不同。

希望这有帮助, 最好的祝福, 汤姆。