Page 52 - 《软件学报》2021年第9期
P. 52
2676 Journal of Software 软件学报 Vol.32, No.9, September 2021
2.4 基于统计分析
(1) 补丁排序模型
基于统计分析的缺陷修复技术指利用统计的方法或学习的技术指导补丁生成的过程或对候选补丁进行优
化.比较早的相关工作是 2016 年由 Long 和 Rinard [24] 提出来的修复方法 Prophet,该方法是在 SPR [67] 基础之上的
进一步优化.SPR 也是 Long 等人在 2015 年提出来的基于人工定义模板的 C 语言条件语句修复技术.Prophet 根
据修复前后的代码特征训练了一个排序模型对 SPR 生成的修复补丁进行排序.Prophet 搜集程序的两类特征信
息:首先是操作,即修复补丁所使用的代码修改有哪些,例如插入语句或替换语句等;另一类特征是程序的静态
特征,例如包含循环语句或检查某个变量的取值等.通过实验表明,该方法可以有效过滤不正确的修复补丁.虽
然 Prophet 使用 SPR 同样的补丁生成技术,却可以多修复一个缺陷.但该结果也表明,单纯通过补丁排序技术难
以实现较大的效果提升.
2017 年,Saha 等人 [83] 采用类似 Prophet 的方法,通过预定义补丁模板指导修复过程;同时,应用机器学习模型
对候选的修复补丁进行排序.基于该方法实现了自动修复工具 ELIXIR.该作者通过实证研究分析实际项目中的
历史修复发现,面向对象语言(Java)程序中存在很多函数调用相关的缺陷,例如替换函数参数、替换同名函数调
用等.基于上述分析结果,作者人工定义了一组补丁生成模板(文中称为 Repair-Expressions),通过搜集缺陷代码
位置可用的程序元素实例化补丁模板生成修复补丁.在此之后,ELIXIR 根据程序的上下文特征,例如使用的程
序元素在上下文中出现的频率、缺陷报告中出现的关键词等,训练一个补丁排序模型,对上述得到的候选补丁
进行排序.该方法的思想与 Prophet 基本保持一致,差别在于 ELIXIR 所定义的补丁模板和排序模型以及针对的
编程语言不同.
2019 年,White 等人 [84] 提出使用神经网络模型对项目中的相似代码进行排序,以供复用生成补丁.基于此,实
现了自动修复工具 DeepRepair.该修复工具预定义了两种修复模板用于指导生成补丁,分别是插入新语句和替
换已有语句.新插入的语句或替换语句来自项目自身代码.DeepRepair 通过预训练的神经网络模型对候选语句
进行排序.在补丁生成阶段,DeepRepair 会使用相似的局部变量替换复用代码中的未定义变量避免编译错误.然
而,实验对比传统的基于遗传算法的自动修复技术 GenProg 表明,DeepRepair 并不能产生更多正确修复补丁.其
中的一个重要原因是:DeepRepair 采用的代码修改模板过于简单,不能很好地覆盖不同的缺陷类型,而神经网络
模型并不能增强其补丁生成能力.
(2) 提取补丁模板用于修复
2017 年,Xiong 等人 [25] 针对 Java 语言中的条件语句修复,提出了高精度的条件语句综合技术 ACS.该技术应
用了 3 种技术手段优化生成补丁的质量:首先,ACS 利用代码的局部性原理,根据变量之间的依赖拓扑关系对修
复条件中的变量选取进行排序,在拓扑图中,距离代码修改位置比较近的变量优先使用;此外,ACS 通过分析代
码中的自然语言注释内容,挖掘程序特征来补充测试所定义的不完整程序规约;最后,ACS 通过统计分析相似项
目中常用的条件谓词,用来对修复补丁所使用的表达式类型进行筛选和排序.通过分析其他项目中的频繁谓词
可以获得领域特定知识,例如变量“hour”通常与常量 12 进行比较等,从而有效提升补丁的质量.实验结果表明:
该方法相比之前方法,实现了大概两倍的修复准确率.
2017 年,Long 等人 [85] 针对 Java 语言的空指针(NPE)、数组越界(OOB)以及类型强转(CC)缺陷,设计并实现
了自动修复技术 Genesis.该技术针对每类缺陷分别准备数据集,然后应用整数线性规划(ILP)算法为不同的缺陷
类型分别推断代码修改模板,并采用二元组〈t1,t2〉的形式表示,其中 t1 表示代码修改之前的语法树,t2 表示修改
之后的语法树.在学习模板的过程中,Genesis 随机地从同类型的代码修改训练集中选取样本进行抽象,然后将
抽象之后的模板应用到训练集上.在尽可能保证修复数量最大化的情况下,控制抽象掉的属性最少(整数规划问
题).在修复阶段,首先将缺陷代码与模板中的 t1 进行匹配,如果匹配成功,可以得到表达式的映射关系,然后根据
t2 生成修复之后的代码.在 49 个缺陷上的实验表明,Genesis 可以正确修复 22 个缺陷.
2017 年,Rolim 等人 [86] 提出的 Refazer 从代码修改样例中学习修改模板.为了方便描述代码的修改操作,作
者提出了一个领域特定语言.基于该语言,代码修改被描述为抽象语法树上的一系列代码重写规则.每一条规则