此C代码编译时没有任何错误/警告。当我运行这个程序时,我可以输入超过16个字符,它会很乐意响应我的所有字符。
永远?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 16
int main() {
char* buffer = malloc(BUFFER_SIZE);
while (1) {
bzero(buffer, BUFFER_SIZE);
scanf("%s", buffer);
puts(buffer); // echo
}
free(buffer);
return 1;
}
(编译时使用:"gcc bufferoverflow.c-o buffer-Wall")
为什么这样有效?它什么时候会坠毁?
基本上,您已经遇到了"未定义的行为"。
因为scanf()
不知道您分配了多少,所以您可以读取比您分配的更多的内容。要避免这种情况,请先使用stdin
中的fgets()
,然后使用sscanf()
。
在这种情况下,最常见的行为是scanf
只是不断向内存写入字符。当然,不会永远。有些东西会阻止它,如果没有其他东西,它会在某个时候"超过内存的末尾"耗尽,在大多数现代系统上,会发生未处理的异常,您的程序会崩溃。在嵌入式系统上,您可能只是停止处理器。
它之所以有效,是因为没有任何重要内容超过了您分配的缓冲区,所以覆盖它不会产生不利影响。当然,这不是必须的,你可能会触摸到一些合理的东西并崩溃,或者更糟的是,在不崩溃的情况下改变程序/系统的某些部分的行为。