Page 201 - 《软件学报》2025年第10期
P. 201
4598 软件学报 2025 年第 36 卷第 10 期
AOR. 下面将介绍 AT, LTGV, SD, LCR 这 4 种变异算子的具体变异过程, 由于剩余变异算子的变异形式类似上述
4 种的其中一种, 所以不再详细描述. 本文实验所使用的数据和代码已进行了开源 (https://github.com/Static-bugs-
Detection-Club).
在介绍算子之前, 简单解释本文所使用的抽象语法树 (abstract syntax tree, AST) 中节点的含义:
a) CASTCompoundStatement: 这个节点可能代表一个复合语句, 通常在 C 或 C++中表示一个由大括号包围的
代码块;
b) CASTExpression: 代表一个表达式, 如算术表达式或逻辑表达式;
c) CASTFunctionDeclaration: 代表一个函数声明;
d) CASTIfStatement: 代表一个 if 语句;
e) CASTLoopStatement: 代表循环语句, 如 for 或 while 循环;
f) CASTDeclarationStatement: 代表一个声明语句, 声明一个变量或常量, 可能包括其类型、名称和初始值;
g) CASTSimpleDeclaration: 代表一个简单的声明, 只涉及基本类型的声明, 如整数、浮点数或字符, 而不包括
复杂的数据结构或类的声明.
(1) AT 变异算子
AT 变异算子是变异过程中优先级最高的算子, 必须首先使用该算子变异抽象语法树, 该算子的作用是添加线
程. 第 1 步, 通过 Eclipse CDT 将原始代码转换成抽象语法树, 获取所有函数名. 然后在 AT 变异中需要创建函数节
点及其子树, 包括线程声明语句节点和线程函数调用节点, 并将其添加到原始代码的 main 函数子树下方. 如果没
有 main 函数, 则选择文件中逻辑上适合作为多线程操作入口的其他函数. 这些函数通常是执行重要逻辑或调度任
务的函数. 第 2 步, 将整个 main 函数子树或选定函数子树添加到原始代码的语法树中, 使其成为其他函数节点的
兄弟节点. 如图 4 所示, 第 1 步时相应的子树创建完成之后, 将子树全部添加到 CASTCompoundStatement 节点的
下方. 而第 2 步将整个 main 函数子树添加到原来的语法树中, 在整个语法树中 main 函数节点与其他函数节点为
兄弟节点.
Step2 CASTTranslationUnit
CASTFunctionDefinition int CASTFunctionDefinition1 CASTFunctionDefinition2
main()
CASTSimpleDeclSpecifier CASTFunctionDeclarator
CASTCompoundStatement
int main()
Step1 subtree ··· ···
图 4 函数节点及其子树
该算子适用场景: 用于需要增加并发执行线程的场景, 特别是在多线程编程中检测和触发 UAF 和 CUAF 类
型漏洞. 该算子主要目的: 通过增加线程来模拟多线程环境, 从而增加漏洞样本的复杂性和多样性. 该算子输入内
容为原始代码的 AST, 输出内容为增加线程后的 AST.
(2) LTGV 变异算子
变异算子 LTGV, 作用是将局部变量转换成全局变量. 在 Eclipse CDT 工具生成的抽象语法树中, 局部变量的
节点名为 CASTDeclarationStatement, 即图 5(a) 处的橙色节点, 而全局变量的节点名为 CASTSimpleDeclaration, 即
图 5(b) 中深绿色背景子树的父节点. 这两种变量在抽象语法树中的表示不仅仅是名称不一样, 它们在语法树中的

