DLLens 论文
现有方法在 counterpart 的选择上:选择不同的后端(CPU/GPU)、同一函数的不同实现方式、相似函数签名(tf.math.add 与 tf.add)。通常,这些在底层有共享的实现或内部及其相似甚至相同,因此无法通过差分测试来暴露 API 实现中的漏洞。DLLens 利用跨库 counterpart 或组合不同 counterpart 实现。
输入有效性:DocTer 通过基于规则的方法从 API 文档提取输入约束;TensorScope 分析部分源代码提取输入约束;
路径约束:ACETest 对 API 源代码的子集做静态分析,排除外部函数(如 std::max),可能无法提取到某些完整输入约束。
LLMs 在 DL 库 API 有丰富知识,理论上可以完成 API counterpart 识别和路径约束的提取:
- LLM 生成的 counterpart 在某些输入条件下无效,导致差分测试出现误报;
- LLM 生成的路径约束不完整。
DLLens 采取 GPT-4o-mini。
- 对于每个 API,DLLens 首先利用类 TitanFuzz 的 prompt 生成 N 个验证输入集,然后应用属性变异来枚举 f 的每个参数的不同值(具体而言,对于一个给定参数,枚举每个属性变异空间 [事先定义] 所有可能属性值来生成一组变异体;对于 float 等非连续参数,为其生成五个变异体;对于字符串或其他类型的参数,不进行变异),由此形成了验证输入集 X \boldsymbol{X} X 。
- 利用 X X X、API 签名,合成一个对应体 f ′ f' f′ ;
- 利用 ∣ f ( x ) − f ′ ( x ) ∣ < ϵ |f(x)-f^{'}(x)|<\epsilon ∣f(x)−f′(x)∣<ϵ 验证 counterpart的有效性;
- 如果 f ′ f' f′ 无效,则根据验证结果构建反馈提示,崩溃情况: [ Crash On Inputs ] , [ Error Message ] [\text{Crash On Inputs}],[\text{Error Message}] [Crash On Inputs],[Error Message];不一致情况 [ Inconsistent on Input ] , [ Expected Output ] , [ Actual Output ] [\text{Inconsistent on Input}], [\text{Expected Output}], [\text{Actual Output}] [Inconsistent on Input],[Expected Output],[Actual Output];
- 由此进行迭代改进 counterpart,确保最终生成的 countepart 有效性。
路径约束提取:
利用 PyCG 和 Joern/tree-sitter 构建 python 与 C++ 调用图,Pytorch 利用 native_functions.yaml
将 Python API 与 C++ 相连接,TensorFlow 用 Python 接口 _execute.execute
访问 C++ 操作符。由此构建语法树,静态分析从其中提取路径约束。
- 遍历条件语句和合理性检查语句中的条件
- 对于每个提取条件,识别涉及变量,检查是否与 API 输入相关;
- 如果无关,则跳过该条件;
- 如果条件涉及变量与 API 输入相关,跟踪输入流动,构造输入约束;
- 如果涉及外部函数,使用 LLM 进行输入约束推断(Prompt:提取条件、输入流动、参数类型、张量属性)
- 添加路径约束
假设有一个执行路径:
if (diag_index < 0) { ... }
if (convert_to_float(k) < 0 && IsVector(k)) { ... }
提取条件:diag_index < 0
convert_to_float(k) && IsVector()
识别相关变量为 diag_indx (diag_index=convert_to_float(k))
k 是 API 输入
过滤不相关条件:二者都与 k 有关,保留。
构造输入约束:diag_index < 0
转换为 convert_to_float(k) < 0
对于 convert_to_float(k) && IsVector(k)
使用 LLM 进行输入约束推断,然后将其有效的推断加入路径约束。(Z3py solver)
在从待测试的API及其对应体中提取路径约束后,DLLens利用这些约束迭代生成测试输入。在每次迭代中,DLLens选择一个路径约束来生成用于差分测试的测试输入。
- DLLens 采取了轮盘赌博选择算法,目的是让很少被选中的路径约束有更高的机会被选中。对于每个路径约束,DLLens跟踪它被选中的迭代次数,记为 c。然后,DLLens定义每个路径约束的适应度分数为 s = 1 c + 1 s=\frac{1}{c+1} s=c+11,每个路径被选择的概率为: p = s i ∑ i = 1 N s i p=\frac{s_i}{\sum_{i=1}^Ns_i} p=∑i=1Nsisi。
- 在使用所选路径约束生成测试输入之前,DLLens会用额外的输入约束对其进行增强,包括重复输入约束、自然约束、属性值约束和错误反馈约束。