addressSanitizer:地址上的堆缓冲区溢出

Posted

技术标签:

【中文标题】addressSanitizer:地址上的堆缓冲区溢出【英文标题】:addressSanitizer: heap-buffer-overflow on address 【发布时间】:2019-01-05 20:04:30 【问题描述】:

我刚刚开始学习 C。

我正在尝试编写一个函数来打开一个文件,读取一个BUFFER_SIZE,将内容存储在一个数组中,然后跟踪字符'\n'(因为我想获取输入的每一行)。

当我将BUFFER_SIZE 设置得很大时,我可以得到第一行。当我将BUFFER_SIZE 设置得相当小(比如42)时,它还不是第一行的结尾,它会在最后打印出一些奇怪的符号,但我想这是我自己的代码中的一些错误。

然而,当我将BUFFER_SIZE 设置得非常小,比如= 10,我使用-fsanitizer=address 来检查内存泄漏。它抛出了一个巨大的错误:

==90673==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000000fb at pc 0x000108868a95 bp 0x7fff573979a0 sp 0x7fff57397998
READ of size 1 at 0x6020000000fb thread T0

如果有人能从一般意义上解释我:

什么是 fsanitizer=address 标志?

什么是堆缓冲区溢出?

什么是地址和线程?在屏幕上看到彩色线程的标志是什么?

以及为什么它说“在地址读取大小为 1..”?

我真的很感激

【问题讨论】:

您的代码中存在错误。 @n.m.有趣的是,这确实是我提到的“我的代码”中的相同错误。我确实分配了一个额外的字节。但我没有输入 0 来确保我结束该缓冲区。 :D 【参考方案1】:

这个错误也出现在 c++ 中。在从超出范围(即 i>n 或 i

【讨论】:

【参考方案2】:

简单来说,使用 new 关键字创建的变量是分段错误,因为所有内容都进入了内存堆区域。

解释 - 您正在尝试访问您尚未为其声明变量的此类地址,以查找所有此类错误重新访问您的所有条件并检查您是否正在访问超出范围的内容或不是。

【讨论】:

【参考方案3】:

什么是 fsanitizer=address 标志?

通常 C 编译器不会为内存访问添加边界检查。 有时由于代码错误,从缓冲区外部进行读取或写入,这种错误通常很难检测到。使用此标志,编译器会添加一些边界检查,以确保您不会使用缓冲区到达其分配之外。

什么是堆缓冲区溢出?

分配后使用数组到达,

char* x = malloc(10);
char n=x[11]; //heap-buffer-overflow

(下溢是在其分配之前到达)

char* x = malloc(10);
char n=x[-11]; //heap-buffer-underflow

什么是地址和线程?

地址是内存中的位置,线程是进程运行代码序列的一部分。

以及为什么它说“在地址读取大小为 1..”?

这意味着您从给定地址读取单个字节。


我认为您的问题是您为缓冲区分配了BUFFER_SIZE 并将相同的BUFFER_SIZE 读入其中。正确的方法是总是声明至少比你读到的多一个字节。 像这样:

char* buff = malloc(BUFFER_SIZE+1);//notice to +1
fread(buff,1,BUFFER_SIZE,fp);

【讨论】:

一个数组通常不在堆上;它要么在堆栈上,要么在 bss 中,具体取决于它声明的范围。堆空间通常由malloc()分配 @Ctx 这只是溢出的例子。 嗯,这不是你声称的堆缓冲区溢出。从技术上讲,它根本不是溢出,因为你不会write超过它的结尾。 在这种情况下有 READ 在分配之外。我猜是在打印缓冲区时。 C 中的这个错误是常青树:D 我从几年前遇到的这个问题中得到了稳定的业力点 ^^

以上是关于addressSanitizer:地址上的堆缓冲区溢出的主要内容,如果未能解决你的问题,请参考以下文章

NSData 转换上的堆缓冲区溢出

Address Sanitizer - 抑制 gtest

如何以编程方式获取 Linux 上的堆地址

.NET - 存储在地址空间中的堆或堆栈上的函数变量?

是否可以将 AddressSanitizer 和 ThreadSanitizer 组合成一个版本?

MFC 程序中的堆损坏