内存将通过代码溢出覆盖什么

时间:2016-05-22 12:27:48

标签: c++ c arrays memory

我收到了以下代码:

char *func(char * a)
{
char b[1000];
strcpy(b,a);
return b;
}

(我知道代码很糟糕,因为我返回数组的地址,当我退出函数时会删除。)我的问题是,如果我输入" a&#将删除/覆盖什么34;,一组2000个字符," b"只有1000个字符数组。我在某处读到了这个问题,他们说通过这段代码我可以知道什么会覆盖。

3 个答案:

答案 0 :(得分:1)

似乎你不熟悉堆栈的想法。当程序控制进入函数时,指向堆栈的指针被赋予程序控制。并且所有局部变量都在此堆栈上分配。当程序从函数返回时,堆栈指针被改变为它的原始值。因此b在堆栈上并为其分配1000个字节。当程序从func返回时,实际上没有任何东西会被删除或覆盖,直到其他一些函数使用该堆栈区域。您可以尝试访问' b'在你从功能出来后它必须工作。但是在调用' func'之后你打电话给另一个功能' func1'有一些局部变量然后更新这些变量将覆盖b指向的内容

答案 1 :(得分:0)

  

什么将被删除/覆盖,如果我输入“a”,一个2000个字符的数组,而“b”只有1000个字符数组。

行为未定义。从标准的角度来看,没有任何保证。有些内存可能被覆盖,或者可能没有。在实践中,可能会覆盖一些内存。

  

纠正我,如果我错了,这个溢出,将重写指针的值。正确?

可以。它可能不会。行为未定义。

将会发生什么取决于编译器,编译器的版本,cpu体系结构,编译选项,如何定义程序的其余部分以及可能的其他因素。

在典型的实现中,返回值适合寄存器并且是编译时常量,因此实际上它不可能存储在堆栈中,在这种情况下它不会受溢出的影响。还有更危险的潜在副作用,例如函数在完全不同的地方返回而不是从它被调用的地方返回。

答案 2 :(得分:0)

如果你传递的a中的C字符串大于你为b分配的空间(1000字节),那么它会愉快地写出b的结尾并向下通过b下面的堆栈中的任何内容。 C字符串没有定义的长度。 strcpy(b,a)将继续将字节复制到b,直到在\0内找到a为止。在函数func的堆栈中,编译器将为b保留1000个字节,然后将返回地址保存到任何名为func的地址。如果a覆盖b,您将覆盖返回地址,当func返回时,您将跳转到某个随机地址并产生可怕的结果。每个编译器都可以自由地将函数的返回地址放在任何地方。也许它将返回地址放在堆栈的顶部。但即使在那种情况下,你也会写下你不应该写的东西。如果你很幸运,你将获得访问冲突。

为防止出现这种情况,您可以使用strncpy(b,a,sizeof(b)-1)并在\0末尾添加b。最好检查strlen(a)并在strlen(a) > sizeof(b)-1

时理智地处理错误

这正是黑客用来打破Windows安全限制的“缓冲区溢出”技术。您调用一个需要C字符串但不检查传入的C字符串长度的Windows函数。传入的字符串会猜测输入缓冲区的长度,最终会正确猜测并覆盖返回地址指向传入的字符串的函数。输入字符串的其余部分包含机器代码指令,然后在Windows函数的安全权限下运行。然后它可以做任何想做的事。

微软很久以前就关闭了这个安全漏洞,但是检查你接受的C字符串长度作为输入参数仍然是一个很好的教训。