消毒剂特殊情况列表

介绍

本文档描述了通过在编译时提供一个特殊文件来禁用或更改消毒工具对某些源代码级实体的行为的方式。

目标和用法

消毒工具的用户,例如 AddressSanitizerThreadSanitizerMemorySanitizer 可能会希望禁用或更改对某些源代码级实体的某些检查,以

  • 加速已知正确的热函数;

  • 忽略执行某些低级操作的函数(例如,遍历线程堆栈,绕过帧边界);

  • 忽略已知问题。

为了实现这一点,用户可以创建一个文件来列出他们想要忽略的实体,并使用 -fsanitize-ignorelist 标志将其传递给 clang 编译器。有关详细信息,请参阅 Clang 编译器用户手册

示例

$ cat foo.c
#include <stdlib.h>
void bad_foo() {
  int *a = (int*)malloc(40);
  a[10] = 1;
}
int main() { bad_foo(); }
$ cat ignorelist.txt
# Ignore reports from bad_foo function.
fun:bad_foo
$ clang -fsanitize=address foo.c ; ./a.out
# AddressSanitizer prints an error report.
$ clang -fsanitize=address -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out
# No error report here.

格式

忽略列表由条目组成,这些条目可以选择分组到部分。空行和以“#”开头的行将被忽略。

注意

在 Clang 18 之前,下面描述的部分名称和条目使用正则表达式变体,其中 * 被转换为 .*。Clang 18 (D154014 <https://reviews.llvm.org/D154014>) 切换到 glob 并计划在 Clang 19 中删除正则表达式支持。

对于 Clang 18,如果文件的第一行为 #!special-case-list-v1,则支持正则表达式。

许多特殊情况列表使用 . 表示字面字符,并且不使用正则表达式元字符,例如 ()。它们不受正则表达式到 glob 过渡的影响。有关更多详细信息,请参阅 此论坛帖子

部分名称是写在方括号中的 glob,表示以下条目适用于哪个消毒工具。例如,[address] 指定 AddressSanitizer,而 [{cfi-vcall,cfi-icall}] 指定控制流完整性虚拟和间接调用检查。没有部分的条目将被放置在 [*] 部分下,该部分适用于所有启用的消毒工具。

条目包含一个实体类型,后跟一个冒号和一个 glob,指定实体的名称,可以选择后跟一个等号和一个工具特定的类别,例如 fun:*ExampleFunc=example_category。两种通用的实体类型是 srcfun,它们允许用户分别指定源文件和函数。某些消毒工具可能会引入自定义实体类型和类别 - 请参阅特定于工具的文档。

# The line above is explained in the note above
# Lines starting with # are ignored.
# Turn off checks for the source file
# Entries without sections are placed into [*] and apply to all sanitizers
src:path/to/source/file.c
src:*/source/file.c
# Turn off checks for this main file, including files included by it.
# Useful when the main file instead of an included file should be ignored.
mainfile:file.c
# Turn off checks for a particular functions (use mangled names):
fun:_Z8MyFooBarv
# Glob brace expansions and character ranges are supported
fun:bad_{foo,bar}
src:bad_source[1-9].c
# "*" matches zero or more characters
src:bad/sources/*
fun:*BadFunction*
# Specific sanitizer tools may introduce categories.
src:/special/path/*=special_sources
# Sections can be used to limit ignorelist entries to specific sanitizers
[address]
fun:*BadASanFunc*
# Section names are globs
[{cfi-vcall,cfi-icall}]
fun:*BadCfiCall

mainfile 类似于将 -fno-sanitize= 应用于一组文件,但不需要将其连接到构建系统。这对于内部链接函数来说非常有效,但对于 C++ 模糊链接函数来说有一个警告。

C++ 模糊链接函数(例如,内联函数、模板实例化)在链接时被重复数据消除。由特定 mainfile 模式忽略的函数(在包含文件中)可能不是链接器选择的占优副本。因此,使用 mainfile 需要谨慎。它可能仍然有用,例如,当以一种确保忽略占优副本的方式选择模式时。(存在远程影响风险。)

mainfile 在为大型代码库启用 ubsan 检查时可能很有用,因为在每次失败时查找触发失败的直接堆栈帧很困难。