繁体   English   中英

缓冲区溢出时程序没有崩溃

[英]Program didn't crash when buffer overflow

我想从键盘上读取一个字符串并存储在buf 我设置了一个char buf[6]数组,该数组最多可以存储5个字符和\\0

然后,我键入123 456 789它包含11个字符和一个\\0 ,该程序仍然可以运行,但是如果我键入更长的字符串123 456 789 123 456 789 ,它将在运行时崩溃。 这两个输入也超出了buf的范围,但是一个可以运行,另一个崩溃?

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void read_str();

int main(){
    read_str();
    system("pause");
    return 0;
}
void read_str(){

    char buf[6] = {};
    scanf("%[^\n]",buf);
    printf("%d\n",strlen(buf));
    printf("%s\n",buf);
}

这只是在分配的内存范围之外写入的未定义行为 它可能现在可以工作,但不能依靠它来工作。 附件J.2 未定义行为中C99标准草案说:

即使显然可以使用给定下标访问对象,数组下标也超出范围(如在声明为int a [4] [5]的左值表达式a [1] [7]中)(6.5.6)。

请注意,第3.4.3未定义行为定义了第2段中的术语( 强调我的 ):

可能的不确定行为范围从完全忽略具有不可预测结果的情况到在以环境特征的书面方式执行翻译或程序期间的行为(带有或不带有诊断消息的行为)到终止翻译或执行(带有发行)诊断消息)。

真正的原因很可能是因为您正在进行函数调用而只是覆盖了堆栈的内容,并且实际上直到尝试编写超出底部的字符后,您才真正拥有了不属于您的内存它的。 即使它不会崩溃,但这几乎总是很糟糕,因为您会覆盖程序出于某种原因放置在其中的值。 毕竟,如果每次改写缓冲区时总是崩溃,那么缓冲区溢出错误就永远不会发生,我们知道它们确实会发生。

例如,您的堆栈可能会向下增长。 进行函数调用时,您可能会获得寄存器值,返回地址,参数值以及其他放置在堆栈中的内容。 然后,直到那时,才会分配您用于buf的6个字节。 如果所有其他的东西占去了,说,12个字节,那么你就可以写18个字符buf ,仍然是不应该只改变触摸存储器,但是你的程序拥有。 由于您的进程拥有它,因此您不会获得非法的内存访问,也不会崩溃。 超过18个字节后,您很可能进入进程不拥有的内存,并且遇到段错误,游戏将启动。

C的原因是您只是行为未定义,甚至发生了奇怪的事情,甚至您都不应该去理解。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM