为什么char name [1]可以容纳超过1个字符?

Sam*_*Sam 4 c buffer gcc segmentation-fault

当我遇到这种情况时,我正在对一个主题进行一些研究.假设以下C代码:

#include <stdio.h>
int main() {
char name[1];
scanf("%s",name);
printf("Hi %s",name);
return 0;
}
Run Code Online (Sandbox Code Playgroud)

我编译-fno-stack-protector并使用超过1的输入进行测试,就像John,令我惊讶的是,它的工作原理!
当输入长于1时,它不应该抛出分段错误吗?
最终它打破了Alexander输入(9),但它适用于任何小于9的内容.
为什么它的输入长于名称数组长度?
PS:我使用Ubuntu(64位),gcc版本4.8.4(Ubuntu 4.8.4-2ubuntu1~14.04)和CLion作为IDE.

das*_*ght 7

这是未定义的行为.您的程序有一个缓冲区溢出,因为它只分配一个字符,这足以存储空的以空字符结尾的字符串.

但是,缓冲区附近的内存尚未分配给您的程序.scanf将您的输入放入该内存,因为它不知道您的字符串缓冲区有多长.当预先确定的字节序列放入你的字符串时,这是一个很大的危险和无数黑客攻击的来源,希望覆盖一些重要元素,并最终获得控制权.

这就是为什么使用%s而不指定大小是危险的.您需要始终添加适当的大小限制%s,否则您的程序将面临缓冲区溢出的危险.

char name[120];
scanf("%119s",name);
Run Code Online (Sandbox Code Playgroud)

此程序是安全的,因为即使恶意用户输入超过120个字符,scanf也会忽略%119s格式中指定的第119个字符的所有内容.