AddressSanitizer 中的“影子字节”是什么?我应该如何解释它们?
来自地址消毒算法 https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithmGitHub 上的页面(也可以从LLVM AddressSanitizer 页面 http://clang.llvm.org/docs/AddressSanitizer.html):
虚拟地址空间分为 2 个不相交的类:
- 主应用程序内存 (Mem):该内存由常规应用程序代码使用。
- 影子内存(Shadow):该内存包含影子值(或元数据)。影子和主应用内存之间存在对应关系。中毒主存中的一个字节意味着将一些特殊值写入相应的影子内存中。
因此,“影子字节”是描述程序可寻址内存状态的元数据。
如果我们看一下 asan 输出:
Shadow byte legend (one shadow byte represents 8 application bytes):
它告诉我们十六进制转储是影子内存,它描述了程序“真实”内存的状态。它跟踪哪些州?
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
...
因此,如果整个 8 字节线是可寻址的,则跟踪(或阴影)它的阴影字节应该具有值00
。如果它是部分可寻址的,则影子字节将是01..07
,这大概是行中可寻址字节的数量。
十六进制转储指向您的值是fa
,或“堆左红区” - 大概这是堆分配周围的某种保护区,用于检测溢出。
来自同一链接:
运行时库取代了 malloc 和 free 函数。 malloc 区域(红色区域)周围的内存中毒了
更广泛地说,这个描述(在程序地址中)
0x602000000005 is located 11 bytes to the left of 5-byte region
[0x602000000010,0x602000000015)
与所示的阴影贴图匹配:
=>0x0c047fff8000:[fa]fa 05 fa ...
假设自然对齐,
- 影子字节
0x0c047fff8000
描述(或者,再次,影子)程序地址0x602000000000..0x602000000007
其中包括您访问的地址
- 下一个影子字节位于
0x0c047fff8001
描述程序地址0x602000000008..0x60200000000F
- 两者都有价值
fa
,意思是“堆离开红区”
- the next影子字节位于
0x0c047fff8002
描述程序地址0x602000000010..0x602000000007
并且有价值05
,意味着 5 个字节是可寻址的。这些是堆分配的 5 个字节。
所有这些都与您的错误部分一致did理解。
-
然而,我仍然很困惑,因为传说中 fa 的意思是“堆左红区”,但它似乎向右 of the 05
and在它的左边。为什么没有“堆右红区”?
我不知道方向性在这里到底意味着什么。堆最初通常沿一个方向增长(传统上,随着堆栈向下增长而向上),但可以分段、释放、合并和重新分配。两个分配之间的间隔是“右”还是“左”,或者两者都存在,或者两者都不存在?我们需要知道的是,这是一个从未分配给用户的有毒堆区域。
如果没有与堆栈左/中/右值相对应的方向,也许它应该只是“堆红区”。
-
在此示例中,ASAN 表示程序超出了 5 字节区域 11 字节,但它显示的 fas 远多于此。
each fa
代表八个字节,正如传说中所说。因此,如果您在分配之前访问了九到十五个字节的任何内容(模算术错误),它将显示在同一个影子字节中。如果您之前访问过一到八个字节,它会显示在next影子字节(就在05
).
剩下的fa
s 只是周围区域的地图,在这种情况下似乎没有帮助,但在其他情况下可能有用。
-
是否有任何正确、详细的文档实际上解释了这些术语“heap left redzone”、“stack mid redzone”、“Global redzone”等的含义?
不知道。不过,它们似乎从用例中相当自然地遵循 - 你到达了红色区域 = 你访问了一个你不应该访问的地址。您始终可以只阅读代码,例如。asan_internal.h https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/asan/asan_internal.h定义了kAsanHeapLeftRedzoneMagic
值,以及asan_allocator.cpp https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/asan/asan_allocator.cpp用它来毒害影子字节。
-
在这种情况下,什么是“影子字节/地址”?
为了完整起见,影子字节是一个字节shadows一组八个通常可访问的程序字节,并跟踪有关它们的一些信息,这些信息对消毒程序有用。
影子地址是影子字节的地址。