怎么了?得到()

时间:2009-05-13 20:37:06

标签: c

让我们考虑这两行:

char input[1];
gets(input);

假设输入是“测试”。 printf(“%s \ n”,输入)=> “测试”,但如果我使用调试器,我看到输入[0] ='t'没有输入[1] ... 究竟发生了什么?

6 个答案:

答案 0 :(得分:10)

那是缓冲区溢出,fyi。为了好玩,请在char untouched[20];之后添加char input[1];并打印untouched。不要使用gets(),使用fgets()或其他带边界检查的内容。

调试器没有显示input[1],因为没有这样的东西。您的char input[1];声明分配长度为1的数组,而不是0到1之间的数组。

答案 1 :(得分:7)

  

gets(s)从stdin读取一行   s指向的缓冲区直到   要么是终止换行符,要么是EOF,   它替换为'\ 0'。没检查   执行缓冲区溢出

http://linux.die.net/man/3/gets

执行gets时,输入被写入s指向的缓冲区。然后它添加一个\ 0。只有't'在输入缓冲区内。其余的,位于堆栈上的连续内存中。 printf打印“test”,因为它可以从s开始读取到第一个\ 0。但是“est \ 0”不在缓冲区之内。

 ------
|  t  |  input - Debugger only sees this position.
 ------
|  e  |  Memory you are stepping onto. Trouble if it doesn´t belong to your proc.   
|  s  | 
|  t  |
|  \0 |
------

当你调试它时,只输入一个char,所以你可以看到所有。

重要的是要看一下“不检查缓冲区溢出是否已执行”。这意味着如果为输入分配了内存,则获取函数并不在意。它将从您指示的点开始复制所有内容。如果您不小心,那么您的输入可以进入重要信息。在某些最糟糕的情况下,这将是您的函数的返回地址(您使用获取的地方)。 “只是犯”这个错误的人会说“wtf正在进行”。故意这样做的人会将您的返回地址指向特定部分,并执行位于那里的代码。

More on Buffer Overflow.

答案 2 :(得分:2)

你溢出缓冲区,就是这样。你写的是不属于你的记忆并且很幸运。

答案 3 :(得分:2)

此:

char input[1];

只保留一个字符的内存值,但是你输入了五个字符。

调试器知道你只有一个角色,并会告诉你它知道你拥有什么。

正在运行的程序会将字符串泼洒在input附近的任何内存中,然后崩溃或逃脱它。在你的情况下,你正在逃避它。

答案 4 :(得分:1)

长度为n的char []将最后一个条目存储在位置n-1中。所以,

char input[1];

表示存储在数组输入中的单个char类型数据,位置为0。

(编辑提供一些澄清 - 第一句措辞太糟糕了。)

答案 5 :(得分:0)

声明一个固定大小为“1”的数组。数组中第一个元素的索引始终为“0”。这就是为什么输入[0]保持字符't'。

编辑 - 其余部分存储在缓冲区外的某个位置(BufferOverFlow)。