繁体   English   中英

malloc()与堆溢出说明

[英]malloc() with heap overflow explanation

我有以下代码:

int main(int argc, char *argv[]) {

    int bufferSize = 8;
    //Setting the buffer size here, which can cause a heap overflow
    char *argsStr = malloc(bufferSize);
    char *anotherStr = malloc(bufferSize);

    //If argv[1] is greater than the buffer size, we will have an overflow
    strcpy(argsStr, argv[1]);

    printf("String 1: %s String 2: %s", argsStr, anotherStr);

}

我想导致堆溢出,所以我导入参数'testtesttesttesttesttesttesttesttest'。

我希望,因为argsStr只有大小为8,它将是'testtest',其余的将溢出到anotherStr(8个字节),但我看到: 在此输入图像描述

所以argsStr是'testtesttesttesttesttesttesttesttest'而另一个是'testtesttesttesttest'

为什么是这样? 我错过了堆溢出或malloc()吗?

printf()不知道或关心你为缓冲区分配了多少内存。 当它打印一个%s格式的字符串时,它会一直打印,直到到达终止零字节。 因此,当它打印argsStr ,它会打印整个内容,即使它溢出了已分配的8个字节。 这就是缓冲区溢出问题的原因 - C指针不包含有关分配内存量的任何信息,因此如果不正确检查长度,则可以轻松访问分配空间外的内存。

anotherStr的内存显然是在argsStr的内存之后分配了16个字节。 因此,当您打印它时,它从argsStr[16]的位置开始,并打印该字符串的最后20个字节。

当然,这是所有未定义的行为,因此您不能依赖任何特定结果。

我所期望的,因为argsStr仅仅是尺寸为8,将它testtest ,其余的将溢出到anotherStr

为了使argsStr字符串在打印后8个字符后停止,第9个字符必须为'\\0' 你的字符串没有它,因此printf不知道在打印%s上的前8个字符后停止。

你的堆溢出了,因为strcpy超过了分配的大小。 它还会破坏malloc存储的“簿记信息”,并进入下一个分配。 当然它不必进入下一个已分配的块,因为它是未定义的行为; 它碰巧在你的特定系统上做到了。

您可以通过valgrind运行程序来判断存在堆溢出。 有可能,当您添加调用以free您分配的内存时,您的程序将崩溃。

如您所知,当您执行malloc时,它会为您提供指向堆中内存块的指针。 堆的确切结构取决于实现。 正如其他人所观察到的那样,您可能会或可能不会获得顺序记忆,您可能会或可能不会得到您要求的内存量。 有一些调试实现malloc可以为您提供所需的内存以及最后一个带有标记的大区域,以便在覆盖已分配块的末尾时查找。 要记住的其他事情是第二个malloc可以在第一个malloc的内存之前或之后。 像MM观察到的那样,你可以做%p来查看块的位置,以便了解它们是否可以相互碰撞。

这就是所谓的未定义行为。 探索未定义的行为非常有趣,并且允许您深入了解实现,但如果它使用不同的版本进行更改,请不要感到惊讶。 几乎可以保证,即使使用相同的(GCC)编译器,它也会在不同的系统上发生重大变化。

如果您真的感兴趣,可以在网上找到GCC运行时库malloc例程的源代码,看看里面发生了什么。 我刚刚搜索了“gcc运行时库malloc源代码”,并发现了一些需要花费几分钟时间才能理解的内容。 这是非常棒的代码。 许多非常聪明的人花了很长时间来研究它。

暂无
暂无

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

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