我正在玩缓冲区溢出,但我对在Mac OS上运行以下简单C程序时发现的内容感到困惑。
#include <stdio.h>
int main(void) {
char buf[2];
scanf("%s", buf);
printf("%s\n", buf);
}
通过将buf的长度设置为2个字节,我预计在输入字符串“CCC”时会导致分段错误,但这不会发生。只有在输入长度为24个字符的字符串时才会出现分段错误。
发生了什么事?它与字符编码有关吗?
感谢。
答案 0 :(得分:5)
一旦溢出缓冲区,程序的行为就不会被定义。任何事情都可能发生。你无法预测它。
在缓冲区之后可能会或可能不会有一些填充字节,这对您的代码执行来说并不重要。你不能依赖它。一个不同的编译器,编译为32位与64位,调试设置......所有这些都可能会在溢出后改变代码执行。
答案 1 :(得分:2)
因为buf
在堆栈上。当你开始覆盖它时,你开始覆盖属于OS将不会捕获的程序的堆栈,这取决于在那里分配的其他内容(例如,编译器创建的寄存器的溢出槽)。只有当您跨越分配的堆栈边界时,操作系统才有机会引发段错误。
答案 2 :(得分:1)
我猜测它与内存布局有关。如果你的进程可以访问你所覆盖的内容(页面映射writable
),操作系统就没有机会看到你做错了什么。
确实,在做这样的事情时,从C程序员的眼中“这是完全错误的!”。但是在操作系统的眼中“好吧,他正在写一些页面的东西。页面是否映射了足够的权限?如果是,OKAY”。
答案 3 :(得分:1)
无法保证您完全会出现分段错误。 char buf[2]
覆盖之后有更多数据可能会或可能不会导致分段错误。
答案 4 :(得分:1)
buf是在堆栈上分配的,你只是覆盖了一个没有使用的区域,很有可能没有人会抱怨它。在某些平台上,您的代码将接受整个段落。