C - 缓冲区溢出问题

时间:2014-11-28 04:20:23

标签: c overflow

以下是该程序的源代码

#include <stdio.h>
% filename: test.c
int main(){
  int local = 0;
  char buff[7];
  printf("Password: ");
  gets(buff);

  if (local)
    printf("Buff: %s, local:%d\n", buff, local);
  return 0;
}

我使用&#34; gcc test.c -fno-stack-protector -o test&#34;编译这个文件,当我运行该文件时,为了使溢出,我需要输入至少13个字符。我认为是因为我只向缓冲区声明了7个字节,这意味着当用户输入至少8个字符时,就会发生溢出。但似乎不是这种情况,为什么?

3 个答案:

答案 0 :(得分:1)

堆栈布局取决于实现。

无法保证local对象将在buff对象之后或之前,或者两者都是连续的。

在您的情况下,可能在buff对象之后插入5个字节(1 + 4)的填充。这种填充是非常常见的,并且出于性能原因通常由编译器插入。填充的大小可能因编译器,编译器版本,编译器选项甚至不同的源代码而异。

要更好地了解布局,只需打印bufflocal个对象的地址:

printf("%p %p\n", (void *) buff, (void *) local);

答案 1 :(得分:0)

gets(buff);

C中没有默认的绑定检查。最好的程序会崩溃,通常会得到未分配的内存,所以它运行正常。甚至有时你已经使用了已经使用过的内存,并且在你遇到问题之前可能没有意识到这一点。

答案 2 :(得分:0)

无法保证堆叠中的项目将被紧密地分配在一起,事实上我很确定它们甚至不能保证以相同的顺序放置。

如果您想了解为什么它没有像您期望的那样失败,那么最好的办法是查看汇编程序输出,例如gcc -S

对于它的价值,CygWin下的gcc 4.8.3在八个字符中失败,正如人们所期望的那样。 以7个字符溢出但是,因为溢出的字符是NUL终止符,所以仍然将local保留为零。

底线,未定义的行为就是这样。对于开发人员来说,大多数烦人的功能是它有时会起作用,这意味着我们有时会错过它,直到代码投入生产。如果UB以某种方式绑定到连接到开发人员私人部分的电极,我保证会有更少的错误: - )

相关问题