警告识别分析文献綜述
摘要:
静态分析工具在软件开发早期的阶段可以自动检测代码异常和缺陷,向用户发出警告信息传达通过静态分析检测到的运行时错误,如今自动静态分析工具如Findbug等也已经被广泛应用,其功能与效率受到很多人青睐,然而,这些工具报告的大量警报通常有相当一部分都属于误报或是无意义警报,还是需要较大的人工检查警报的成本,而只有那些需要程序员关注和进行修改的警告才是有效的警告,因此如何识别有效警告值得研究。
本文研究了35篇相关论文,提取其中使用的方法,分为机器学习、警告排序、交互式、修剪/分类、启发式方法、动静态分析结合六类,我们分析其算法流程并分析其可取之处、缺陷以及意义,并据此设想未来研究方向以及应用实践。
最终我们发现不同方法都有其优势与劣势,实际应用中可以将其中不同方法结合,或是依据不同情境选择合适的方法,这样才能有更好的识别效果,同时结合的程度以及不同方法应该在何时使用则是值得研究与对比的部分。
关键词: 静态分析; 有效警告识别; 机器学习; 启发式方法; 交互式; 修剪/分类
Static analysis tools can automatically detect code exceptions and defects at the early stage of software development, and send users warnings about runtime errors detected through static analysis. Now automatic static analysis tools such as Findbug are widely used, and their functionality and efficiency are favored by many people. However, A large number of alarms reported by these tools are usually false alarms or meaningless alarms, which require a large labor cost to check. Only those warnings that require programmer’s attention and modification are valid warnings, so how to identify valid warnings is worth studying.
This paper studied 39 relevant papers and extracted the methods used in them, which were divided into six categories: machine learning, ranking of alarms , interactive, pruning/classification, heuristic method and static-dynamic analysis combination. We analyzed their algorithm flow and analyzed their merits, defects and significance, and based on this, we proposed the future research direction and application practice.
Finally, we find that different methods have their advantages and disadvantages. In practical application, different methods can be combined, or select appropriate methods according to different situations, so as to have better identification results. Meanwhile, the degree of combination and when different methods should be used are worth studying and comparing.
Key words: static analysis; actionable warning identification; machine learning; heuristic method; interactive; pruning/classification
1 引言
在过去的数十年里,软硬件的发展速度飞快,现在我们的生活已经离不开各种软件了,程序的安全保障变得至关重要,怎么让开发软件的过程花费更少的成本、更快速方便、更少地出现缺陷和故障也成为了核心需求。虽然静态分析工具在软件开发早期的阶段可以自动检测代码异常和缺陷,向用户发出警告信息传达通过静态分析检测到的运行时错误,如零除、溢出/欠溢出和空指针解除引用等。然而,这些工具报告的大量警报通常有相当一部分都属于误报或是无意义警报,还是需要较大的人工检查警报的成本,因此人们便希望找到一种最合适的技术能够自动识别出有效的警告。
我们研究了现有的有效警告识别技术,它们大多旨在将静态分析和动态警告质量保证技术相结合,以改进静态分析错误检测并减少错误警报。本文的目的就是概述各种警报处理方法、分析它们如何解决有效警告识别的困难和挑战、对比它们使用的技术和优缺点、设想未来的研究方向会是如何的。
为了研究这些问题,我们进行了系统的文献检索,首先进行基于关键字的数据搜索,然后阅读具体内容,从中选取了最符合研究目标的39篇文献。我们仔细分析对比了这些资料,总结出了五个目前程序报警遇到的困难和挑战,依照使用到的技术类别把文献分为了七类。我们最后发现每一种方法都有其优点和局限,并且是可以互补的,实践中可以把这些技术通过多种方式组合在一起以达到最佳效果。
2 问题与挑战
2.1 静态分析工具产生误报多
在我们阅读到的文献中,大部分[1][2][4][5][6][7][8][12][13][21][22][28][29][30]都特意强调静态分析产生误报的问题,静态代码安全检测与动态应用测试不同之处在于,静态代码分析直接面向源码,能够检测所有的代码级别可执行路径组合,快速准确分析语义缺陷及安全漏洞。然而,只对代码进行静态错误分析在实践中存在很高的误报率,导致开发和测试人员经常花费大量的时间和精力在错误警告上,结果到最后发现是误报,软件开发的各方面成本就此上升。
静态分析之所以会产生大量误报的可能原因有:
1.静态应用程序测试工具本身基于一些算法,对程序数据、控制流分析,预判程序中存在的潜在问题。而算法耗时与准确度成正比。作为工具产品,高运行、高准确度的检测并不容易实现。因此在设计中存在简化、取舍,导致精度流失,运行时间和算法精度之间要达到平衡,因此产生误报。[12]
2.由于被分析的软件并没有被真正地执行,静态分析工具并不知道程序真正要做什么行为,也不理解程序员的意图,导致高估或是误推测软件行为[6],发出与真正缺陷不对应的虚假警告。
3.可能存在过度分析,过度警报,即对一些微小的不合规范的低严重性的地方发出警告,比如样式类错误、strcpy()这样可能存在漏洞的函数、对内存的操作等等[1],这类需要大量努力修复而几乎没有感知到的好处的实际缺陷,通常被称为噪声。
4.静态代码警告工具不根据特定的输入去做出评价,也不使用任何正在被执行的研究代码产生的反馈。[11]
2.2 静态分析工具有局限性
①因为人工检查在现今的静态分析中必不可少,因此就难免会存在用户的负面反馈[2][3],指用户在检查警报时对于警报的内容产生了错误的判断,例如误报当真,警告含义模糊导致理解错误,从而对整个代码的后续迭代产生了负面的影响。
②静态代码分析工具(sat)的一些特点也限制了其在实践中的广泛适用性。一个关键问题是,sat在检查违规行为方面必然不够精确;换句话说,他们报告的警告可能与实际错误相符,也可能与实际错误不符。结果是,静态分析工具第一次在项目上运行时,很可能会报告数千个警告,这使开发人员无法通过它们筛选来选择那些更相关且应该修复的警告。在实践中使用sat的另一个相关问题是,理解由警告强调的问题并提出合适的解决方案通常是非常重要的。
2.3 启发式标签过于乐观
启发式指 “自我发现的能力”或“运用某种方式或方法去判定事物的知识和技能”,静态分析的静态启发技术指的是在静止状态下通过缺陷的典型特征识别缺陷的方法。启发者算法是一种基于直观或经验构造的算法,在可接受的花费(指计算时间、计算空间等)给出待解决优化问题的每一实例的一个可行解,该可行解与与最优解的偏离程度一般不可以事先预计。
因此,启发式产生的标签可能与人类预言不符[12],如果在实践中采用,会对其真实性能过于乐观,但它给出的分析结果往往是不健全的,给用户带来”虚假的繁荣”。
2.4 潜在缺陷未被发现
由于静态分析工具并没有实际执行,可能会有某些错误或危险的操作没有被识别出来,更可能的是识别成了错误的警告,导致用户关注了错误的地方甚至无视了警告,为软件埋下了潜在的缺陷。而一次软件开发可能包含数千次的提交,若这些潜在缺陷没有被及时发现出来,它的隐患、造成的后果以及发现和修复的难度可能会越大[5]。
2.5 动態分析的弊端
动态代码分析是在执行时对程序执行的分析。 这意味着您必须先将源代码转换为可执行文件。因此无法检查包含编译或生成错误的代码。 该检查是通过将一组输入数据馈送到要分析的程序来完成的。 因此,动态分析的有效性直接取决于测试输入数据的质量和数量,正是这些数据确定了测试结束时代码覆盖的程度。动态分析相较于静态分析拥有对代码的实时分析与反馈,会带来更优的精度,但其弊端也不容忽视:
1.不能保证完整的代码覆盖率。 也就是说,您不太可能通过动态测试获得100%的覆盖率。[7]
2.与静态分析相比,动态分析更难以使用,因为您需要向程序中馈入足够的数据以获得更好的结果并获得尽可能多的代码覆盖率。[7]
3.动态分析测试昴贵,成本高[5]
4.动态分析器不善于检测逻辑错误。 例如,从动态分析器的角度来看,始终为真的条件并不是错误,因为这种不正确的检查只会在编译步骤的早期消失。[8]
3 研究现状分析
我们使用作者自己提出的标签对找到的文献进行初步分类。然后把具有相似方法的文献被再组合在一起,主要用其中处理错误警报的方法作为判断的对象。当发现一篇论文结合了多种方法,即可以被分成多个类型时,我们选择一种更主要、更好的方法,这主要由论文标题得出。
于是,我们得出了以下六类处理警告的方法:
1.AI,机器学习:训练神经网络学习什么样的警告是误报并消除掉。
2.排序:警报和源代码的各种特征、错误/警报修复和代码更改的历史记录等 用于对警报进行排名或优先级排序。
3.交互式:通过用户交互协同地将合理但不精确的分析与精确但不合理的启发式方法相结合,在每轮迭代到找到并优化问题,最大化收益。
4.修剪:警报分为可操作或不可操作,不可操作的警报被修剪。
5.启发式方法:
6.动静态分析结合:静态和动态分析相结合以处理警报。
除此之外,少量论文里也提到了使用聚类方法,根据警报之间的相关性将其进行聚类,也能有效减少多余的检查工作量。
3.1 AI,机器学习
静态代码警告工具的显著特点是它们不根据特定的输入去做出评价,也不使用任何正在被执行的研究代码产生的反馈,静态分析工具往往会产生大量误报,而经验丰富的开发人员知道哪些错误是重要的,哪些错误可以被安全地忽略,因此使用机器学习、AI的方法来对这些经验丰富的开发人员的操作进行学习是消除误报的一种常用方法,然而要用机器学习就需要数据以及合适的机器学习算法,解决这两个问题才能更好地识别有效警告。下面介绍几种方法:
① 深度学习与非深度学习:在[11]中作者分别使用了三种非深度学习方案随机森林、决策树、线性支持向量机(SVM)以及三种深度学习方案深度神经网络DNN、卷积神经网络CNN、加权DNN来进行实验,以Wang等人中提出的黄金集[15]为基础创建用于本文训练和测试的数据集,以召回率,错误警告率以及AUC三个指标来评估,结果显示虽然深度学习的方法也有很多项为最佳结果,但是综合来看非深度学习的线性SVM的效果最好(较低的假警报、较高的召回率和AUC),尽管深度学习近些年来在软件分析领域一直被推崇,但是在消除误报这个领域,且它的表现不如线性SVM,运行时间更是非深度学习方法的近20倍,原因是虽然数据多,但是这些庞大的数据集的有效内在维度很低,也就是说深度学习与静态警告数据集的复杂度不匹配,而根据Principle of Parsimony,在低维的数据上使用复杂的方法是有害的,所以在消除误报的领域,深度学习的性能反而不如非深度学习。
因此复杂的方法的效果并不一定比简单的方法好,选取合适的机器学习方法能更好更高效地识别有效警告,且能降低成本,加快进程。这在未来的相关研究中具有很好的指导意义。
② 增量主动学习:Yang等人在2021年提出了一种增量AI工具[16]来学习如何将误报与有效警报区分开以达到识别有效警告的目的,然而有监督的机器学习技术需要有标签的数据进行学习,而且要获得质量较高的标记数据有时会很耗时且昂贵,在识别有效警告领域,要训练一个能识别有效和无效警告的分类器需要数十万的标本,如果人工标注,成本会相当高,且标注需要专业知识,因此本文引入主动学习来进行数据标注。
这样做的原因是主动学习通过小部分已标记数据训练,然后为未标记数据申请更多标签,这样就可以减少所需的标记数据量。这对于机器学习的模型来说可以减少所需数据量,降低成本。
作者又选择了三种机器学习算法支持向量机(SVM)、随机森林(RF)和决策树(DT),并测试了有监督的SVM、RF、DT以及主动学习和SVM、主动学习和RF、主动学习和DT,得到结果发现增量主动学习可以获得高AUC,不比大多数数据集的监督学习差。
接下来作者通过实验证明在静态警告识别中应用增量主动学习模型可以帮助以更高的优先级检索可操作的警告,并减少在没有足够版本历史的软件项目中消除错误警报的努力。在静态警报识别场景中实施主动学习模型时,要检索多少样本是一个关键问题。过早或过晚停止将导致丢失重要的可操作警告或浪费不必要的运行时间和CPU资源。然后作者通过在九个数据集上实验发现在大多数数据集上主动学习只需要20%-30%的数据就可以识别90%以上的有效警告。作者通过一系列实验最终说明主动学习在处理不平衡数据集的静态分析的信息检索问题上是有效的。
Yang等人提出的增量主动学习方法在静态分析识别警告领域的应用很有意义,将增量主动学习和常用的机器学习算法结合可以大幅降低成本并且提高效率,同时这也是对机器学习如何获取知识这一问题的有效回应。这也进一步地提示相关研究者,不同方法结合使用可能会有更好的效果。
③ 构建完善的真实世界数据集:针对静态分析工具产生大量误报问题,已有不少后处理的解决方法,但是大多数这些方法只处理少数静态代码分析警告类型,并且基于小规模的数据集进行评估,显然具有局限性和不稳定性,因此可以利用机器学习和更大的数据集来更好地解决误报问题。
PÉTER HEGEDŰS等人在2022年提出构建一个最广泛的真实世界公共数据集[13],并据此训练一个机器学习模型来更好地识别有效警告。
PÉTER HEGEDŰS等人针对SonarQube3这个开源平台,想借助它的提交历史来获得相关警告,作者使用数据挖掘技术挖掘了GitHub上Java项目的历史,保留哪些有SonarQube使用迹象的项目来获得适合构建假阳性静态代码分析(SCA)警告过滤方法的真实世界数据集。为了找到真阳性样本,即开发人员已修复的SonarQube警告,作者分析了2010年之前Java项目存储库的代码历史,以找到明确的Sonar Qube警告修复提交。为了找到假阳性的SonarQube报告(即,识别开发人员的动作A3),作者在GitHub上的Java项目存储库中执行代码搜索并在经典REST API的帮助下执行了所有挖掘步骤。然后执行了一个筛选步骤,删除了只有真阳性或假阳性样本的SonarQube问题类型。在这个过滤步骤之后,最终得到了来自9958个不同Java项目的160个警告类型和224484个警告样本。
接着作者用数据集训练了基于代码上下文的word2vec机器学习模型,对包含SonarQube警告报告的代码片段执行二进制分类任务,输入包含警告的代码上下文的矢量表示,输出二进制标签,该模型对160种不同类型的SonarQube警报进行分类,准确率为91%(最佳F1得分为81.3%,AUC为95.3%),识别出77.8%的假阳性警报,而平均只过滤出(即误分类)8%的真阳性警报。
许多现代CI/CD已经包含了SonarQube分析,而作者的方案可以轻松集成到该分析中,非常适合实际应用。同时作者构建的数据集也为有效警告识别领域提供了一个非常好的知识库,便于后续研究以及训练机器学习模型,这是非常有意义的。这种方法也是对知识库问题的一个正面解决,即缺少知识库,就构建足够大且可靠的知识库来为机器学习模型提供足够的数据,同时一个好的数据集的建立也可以为后续相关研究提供一定便利,推动相关研究的进行。
3.2 警告排序
排序方法是对那些有很大概率是真实缺陷的报警进行优先级排序,并使用警告特征来计算每个报警可操作的可能性。
在我们研究的多篇论文中,Jung等人(2005)提出使用句法报警上下文作为贝叶斯的输入[32],计算每个报警的真实概率,并在报警前根据概率对报警进行排序。Kim和Ernst (2007a,b)提出了一种基于从源代码库中挖掘出来的软件变更历史特征的警告优先排序算法[33],而他们的基本思想是,通过修正更改消除的警报是重要的。在类似的思路上,Williams和Hollingsworth(2005)提出了一种利用软件项目的源代码更改历史来驱动和帮助改进缺陷搜索的方法[34]。针对其他排序方法的弱点(即在检查报告时,排名应该是自适应的),Kremenek等人(2004)利用报告和用户反馈之间的相关性行为进行警报排名[35]。与聚类方法相比,该方法需要对所有排名的报警进行检查。
下面给出两篇具体论文的研究分析:
①在[18]中QIN等人提出了一种构建基于机器学习的警告优先级排序模型的方法。在一般的警告优先级模型中,通常为每个警告分配一个置信度评分,分数越高越有可能是真实缺陷,以此来弥补静态分析SAT在产生警告时产生了大量无效警告的情况。目前的警告优先级排序方法主要依靠警告特征计算权重集来获得最终置信度得分[19],但警告特征[20]-[22]间存在冗余和不相关性,为了选择合适的特征,QIN等人提出在真实的、开源的、大规模的数据集上构建基于ML的警告优先级排序模型,在探索了91个预警特征,并使用特征选择算法找到了预警特征子集后,QIN等人证实了基于ML的警告优先级排序模型优于随机排序算法。图3.2.1 框架预览
[18]中采用递归特征消除(RFE)算法迭代消除预警特征,选取最优特征集。RFE算法从所有原始特征集开始,在每次迭代中,RFE算法构建一个基于ml的预警优先级模型,并从当前特征集中去除最不重要的特征。最后,返回获得最佳优先级性能的特征子集(即最优特征集)。QIN等人选取了6种常用的ML模型,包括朴素贝叶斯(NB)、逻辑回归(LR)、K最近邻(KNN)、随机森林(RF)、决策树(DT)和支持向量机(SVM),将静态分析预警数据集中的最优特征集和预警标签分为训练集和测试集,利用ML模型从训练集中学习基于ML的预警优先排序模型。
实验证明了基于最优特征集的警告优先排序模型具有良好的性能,且其中基于LR的警告优先排序模型性能最好。
②对于警报排序时训练的数据集 ,Athos Ribeiro等人给出如下处理假设[29]:
i. 数据提取:将来自不同工具的警报转换成统一的格式,并对每个警告应用标签,以区分它们是真阳性还是假阳性并将每个警告与特定的特征相关联,这些特征将组成一个数据集来训练我们的预测模型两点来对工具提供信息的规范化;
ii. 选择数据来源:通过在先前选定的源代码上运行静态分析器,并将触发的警告与实际的软件缺陷相匹配,来获得标记静态分析警告的数据集;
iii. 多个工具收集标记警告:对测试套件进行裁剪后运行静态分析器生成静态报告,并检查标记的警告集;
iv. 从标志警告中提取特征:特征包含生成警告的工具名称、同一文件中的警告数量、类别、冗余级别、邻居数量等
v. 依据数据集,构建预测模型,对每个触发警告分类为真阳性和假阳性,结果用于排序。
通过从准确率、精度、召回率等纬度的评估,Athos Ribeiro等人验证了此处理方式的合理性。[29]
3.3 交互式
XIN ZHANG等人提出了一种交互式方法来解决静态分析警报的误报问题[1]。通过用户交互,他们的方法协同地将合理但不精确的分析与精确但不合理的启发式方法相结合。在每轮迭代找到并优化问题,最大化收益,他们已经在Ursa工具中实现了这个方法。
该工具可以为声明性逻辑编程语言Datalog中指定的任何分析提供交互式警报解决方案。Ursa在最先进的静态数据竞赛分析中具有效性,使用一套8个Java程序,每个程序包含41-194个KLOC(千行代码的意思)。 Ursa能够消除每个基准测试74%的误报,每个问题的平均收益为12倍。
这个方法的关键思想是,组合方法 (就是那个把合理但不精确的分析与精确但不合理的启发式方法相结合的方法) 不是以可能不合理地抑制误报的方式直接应用给定的启发式方法,而是向用户提出有关启发式方法所针对的根本的真实的原因。如果用户确认了它们,就只有在用户知情的情况下,才会应用启发式方法来消除误报 。
为了有效,组合办法必须实现两个关键目标: 概括和优先次序,概括:与消除的误报数量相比,向用户提出的问题数量应该少得多,大多数警报通常是一组相对较少的常见根本原因所引发的,所以检查这个单个根本原因比检查多个警报更容易。优先次序:由于由不同根本原因导致的误报数量可能会有所不同,因此用户可能希望只回答收益相对较高的问题,所以通过迭代方式与用户交互来实现这一目标,而不是一次提出所有问题。
他们使用来自 Chord [Naik 2006] 的静态数据空间分析,它是上下文和流敏感的,并结合了线程逃逸分析、可能发生的并行分析和锁集分析,即图3.3.1中的推导。
图3.3.1 示例程序中数据空间的推导
图3.3.2 工具评估
他们在实践中证明了方法的有效性,通过只问几个问题来消除大多数误报,并优先考虑高回报的问题。然而,这种方法也有其弊端,即分析结果十分依赖于程序员,倘若程序员对警报是否真实和重要并不熟悉,仅凭直觉或个人喜好进行交互,那些分析结果可能和真实情况有很大的偏差,而且这种方法可能只适合用在开发阶段,代码测试和审查阶段可能不会有这种迭代交互的机会。
3.4 修剪、分类
通过分类的方式,可以区分警告是可处理还是不可处理。不可操作的警告将被修剪,不会报告给用户,因为这些警告更有可能是误报。
我们研究了近几年有关警报修剪分类方法的众多论文,其中Ayewah等人(2007)讨论了产生的报警的种类,并将报警的类型分为假阳性、小bug和严重bug[36]。Ruthruff等人(2008)提出了一种逻辑回归模型,基于从告警本身提取的33个特征来预测FindBugs发现的可操作告警[37],并使用一种筛选方法快速丢弃预测能力低的特征,以构建具有成本效益的预测模型。Hanam等人(2014)提出了一种区分可操作和不可操作告警的方法,方法是根据每个静态分析告警周围的代码寻找相似的代码模式[38]。Flynn等人(2018)发展了和测试了映射到CERT规则的静态分析告警的四个分类模型[39],使用了多种静态分析工具和从告警中提取的28个特征的新颖组合,可见关于警报分类的研究在不断进步和发展。
下面给出两种具体模型的分析[2][28]:
①静态分析工具的两个挑战是虚假的误报和未有采取行动的合法警告。因此Joseph R. Ruthruff和他的团队做了一个工具,使用筛选方法来快速丢弃预测能力低的影响因素,并经济高效地构建预测模型[2],通过识别开发人员将要处理的合法警告来帮助解决这两个挑战,从而减少测试人员对程序内报告的数万个警告进行分类的工作量。他们从 Google 的数万个静态分析警告中抽样,构建了模型来预测错误警告是否为误报。
他们的工具使用逻辑回归分析,一种分类数据分析,用于预测服从二项分布的因变量值 。逻辑回归模型根据一系列系数的总和乘以特定自变量的来预测单元 i的因变量 y 的值。为了在数学上表征这一点,设 Xi = (Xi1,…,Xin) 是单位 i 的自变量值的向量。设 β = β0,β_1,…,βn 是通过将模型拟合到现有“模型构建”数据集来估计的系数,其中 β0 称为模型“截距”。“ 逻辑回归模型通过计算给定 _Xi 的 Yi = 1 的概率来预测二进制值 Y i for i,这个模型的概率如图3.4.1所示。
图3.4.1 模型的概率
他们根据自己在 Google 静态分析警告方面的经验,以及其他在其他软件工程领域建立回归模型的研究人员的经验,他们决定专注于更轻量级的复杂性度量,并且可以在大型代码库上非常快速地计算,于是选择了因子和相关指标,即图3.4.2所示。
图3.4.2 静态分析警告和程序的因素
他们的筛选方法分为几个阶段:
第一阶段:考虑了5%的静态分析警告和源代码。此阶段的目标是考虑一小部分警告,并消除几乎没有构建准确模型所需的预测能力的影响因素。
第二阶段:如果消除后留下六个或更少的因素,就停止筛查,并根据剩余因素使用剩余的95%的警告收集数据。否则,在第二阶段考虑了另外 20% 的静态分析警告,然后使用偏差分析来消除检验统计量 p 值大于 0.50 的因子。第三阶段:使用接下来的 25% 的警告,现在分析的警告占所有警告的一半。这里的排除标准更严格:p 值大于 0.20。之所以选择这样做,是因为到目前为止,已经收集了大量数据,可以做出明智的判断。
第四阶段:如果剩余的因素超过六个,则这些因素用最后 50% 的数据来分析。这将消除 p 值不显着且大于 0.10 的因子。然后使用剩余因子作为自变量在 R 中拟合对数回归模型。
图3.4.3 基于筛选因子构建模型 ,预测误报的模型
分析然后评估预测精度:逻辑回归模型在预测误报和可操作静态分析警告方面具有准确性。可以看出,筛选模型在预测假阳性和基于真实缺陷的行动警告方面通常是最准确的。
3.4.4 预测精度
这个基于筛选的模型能够平均在85%的时间内准确预测误报警告,在70%的时间内准确预测可操作警告。此外,筛选模型始终比现有预测模型表现更好。然而,这种方式需要额外的数据收集,收集构建全数据回归模型所需的数据可能需要大量时间,必须想办法尽快减少多余的影响因素,降低根据这些因素收集数据的成本。这个方法比较适合大型项目的后期测试中,当你认为一个缺陷有许多的可能因发因素,又无从查起,焦头烂额,就可以使用它。
②YU等人选择了13个基本分类器和两种集成学习方法构建了一个基于机器学习方法的二元分类模型[28],将报告的警告被分类为有效警告(真实的缺陷)或无效警告(假阳性),并对分类为无效警告的报告报警进行修剪,以减少人工检查的工作量。该实验在4个开源C项目上对该方法进行了评价,分类结果表明所提出的模型在实践中取得了较高的性能和可靠性。然后进行一个基线实验,以评估提出的模型的有效性与传统的对比。
该实验不同的特点有以下四点:
1、选择两种集成学习方法和13个基分类器建立自动缺陷识别模型。
2、在变量级别上设计了一组新工件特征,称为变量特征(VC),用于构建所提出的模型。
3、在四个开源C项目上进行了实验,以评估我们的方法在识别来自同一项目的报警的情况下的性能。
4、变量特征由三个不同的单一属性评估器进行排序,以确定这些特征对模型的影响。
(图:模型构建过程)
YU等提出了一种基于警报的变量特征(vc)并给出了其语义度量:利用抽象语法树(AST)提取源代码语义。在分析源代码文件时,将注意力集中在数据流的表述和相关变量的条件谓词上,通过生成向后的程序片来减少要检查的语句数量。一个反向的程序切片将包含相关变量的语句作为种子语句,提取可能影响种子语句结果的三种类型的语句作为特征,分别是赋值语句、引用语句和控制流语句。
(图:分类器和集成学习方法)
③Diego Marcilio等人则提出了一种Java程序转换技术SpongeBugs[30],它通过自动提供修复建议来提高SAT的实际可用性,即对源代码进行修改使其符合分析工具检查的规则。它的大致步骤为:
a、查找可能表示违反规则的文本模式。
b、对于步骤1中确定的每个匹配,在AST中执行完整搜索寻找违反规则的行为。
c、对于第2步中确认的每个匹配,实例化规则的修复模板生成违反规则的实际修复。
通过在12个流行的开源项目上运行并提交了它在项目中请求生成的大部分修复(总共946个),Diego Marcilio等人证实了SpongeBugs可以成为一种有效的方法,帮助程序员修复静态代码分析工具发出的警告——从而有助于提高这些工具的可用性,进而提高软件系统的整体质量。
此外还有一种自动将代码转换模板应用到大型代码库的方法Coccinelle[23]。它支持用户定义mod(通用的)、复杂的模式,以捕获语义信息。它的实现将模式表示为CTL公式,并将其应用表示为程序控制流图上的模型检查问题。Coccinelle的主要应用是支持大型代码库的演进:当API或语言特性发生变化时,手动重构很容易出错,因为引入不一致或其他错误的风险很高。
3.5 启发式方法
① 软件系统中缺陷的检测分为两个研究领域:静态代码分析和历史数据的统计建模。静态分析有误报的问题,相比之下,统计错误模型用历史开发信息来提示有风险的文件或提交,即潜在的缺陷。模型中使用的预测因子包括产品度量(例如提交中更改的行数)和过程度量(例如开发人员对文件的专业知识)统计错误模型的优点是它们提供了对提交和文件中的字段缺陷的合理预测[17]。缺点是预测不是细粒度的,整个文件都会被标为有风险。
于是,Querel L等人便开发了一个名为 WarningsGuru 的工具,它结合了这两种方法,使用统计模型来识别哪些提交可能包含缺陷,并引入的静态分析警告显示出特定行号。他们还开发了一种跟踪提交的警告的技术,用它来追溯将警告分配给失败的构建。
图3.5.1 WarningsGuru的体系结构
统计模型认为有风险的提交会突出显示,还会显示新警告和现有警告的数量。例如,图3.5.2中,显示了每次提交的警告和新警告的总数,以及 CommitGuru 的 统计风险预测,更改的文件有34个现有的警告提交,”b36bb31fe4”则不被认为是有风险的,此提交中没有引入新的警告。
图3.5.2 每次提交的警告分析
图3.5.3 显示 CommitGuru 度量值时,提交的异常值以红色突出显示。例如,“添加的行”异常高,大型提交往往有风险
他们通过单独使用统计模型,发现 CommitGuru 将 25% 和 29% 的提交标记为 risky。当将其与 WarningsGuru 中的静态分析相结合时,两个项目的风险提交和警告数量分别为 20%,新警告的数量分别为 3% 和 6%。
可见通过将统计模型与静态分析相结合,可以大大减少开发人员必须检查的提交和警告。他们这个工具也正在与加拿大发展部的KDM分析和国防研究合作,可见其有效性。然而这种方式也不能在所有时候都一帆风顺,因为统计模型不可能在可用、可靠、性能等维度上都做的很好,总会有覆盖不到的地方,作者也说只能用来标注有风险的提交的行,而且用于错误定位的静态分析工具自身都有局限,不能准确定位,结合起来一样会有误报的发生。
② 关闭-警告启发式方法:许多研究中使用启发式算法来对警告进行识别,如图3.5.4所示,构建一个数据集作为训练版本,并不断收集警告直到测试版本,最后在测试版本使用一段时间后选定一个参考修订版,使用关闭—警告启发式方法作为警告预言时,对于一个给定的修订版本,里面的每一个警告都要与参考修订版本对比,如果参考修订版中不再存在该警告(关闭警告),则该启发式算法认为该警告是有效的。如果在给定版本和参考版本中都存在该警告(开放警告),则启发式认为这是错误警告。如果包含带有警告的代码的文件已被删除,则警告将被标记为未知,并从数据集中删除。
但是,Kang等人通过研究证明这种启发式方法并不稳定[12],他们首先通过调整测试修订版本和参考修订版本之间的时间间隔,发现得到的有效警告的比例并不稳定,从图3.5.5里可以看出,8个项目中有4个项目的有效警告比率保持一致,而其他4个项目的有效警告比率增加了10%以上。总体而言,当将测试和参考文献修订之间的时间间隔从2年改为4年时,平均有效警告比率增加了14%。
接下来Kang等人又通过实验发现只有47%的关闭警告被人工注释人员标记为有效的,这意味着许多关闭警告是无效的。许多关闭的警告只是偶然关闭的。这说明虽然封闭警告启发式认为可以通过删除文件来删除一个警告,但它没有考虑其他情况,即警告可以通过修改代码顺便删除,但这并没有修复警告所指出的错误。这也说明应该考虑更多的信息,启发式没有足够的鲁棒性。
除了关闭警告有可能不是有效警告外,开放警告也有可能不是误报,也可能是被忽略的有效警告,Kang等人通过调查使用了Findbug过滤器文件的项目中被认定是错误的警告和开放警告的比例,最终发现平均只有31%的开放式警告被开发人员明确表示为错误警报,这表明只有少数开放警告是假警报。尽管其余打开的警告可能是错误警告,但它们也可能是尚未检查的有效警告。
综上所述,关闭—警告启发式算法并不是合适的警告预言,因为它的分类结果会因为参考版本的改变而改变,同时得出的关闭警告中只有部分被人工注释人员认定为有效警告,同时关闭警告和开放警告的分类与有效警告和无效警告的分类并不是完全相同的,关闭警告中会包含无效警告,开放警告中也会包含有效警告,因此这种启发式算法虽有可取之处,但是并没有足够的鲁棒性以及稳定性。未来应当将启发式和手动标记结合一下构建数据集。
3.6 动静态分析结合
静态分析只要源代码或二进制文件,而无需执行。此方法速度快,并且没有运行时间开销。然而,静态分析非常简单,会产生很多的误报和漏报。另一方面,动态分析涉及软件的运行。在动态分析的情况下,误报和误报的问题较少,因为它们通过运行测试用例进行分析,而开销就比较大,因此可以两者结合互补输出最佳结果。使用动态分析检查静态分析警报是否为真错误,并且见证故障的测试用例将作为错误场景报告给用户。
在[7]中,Aggarwal A等人解释了如何有效集成静态和动态分析的方法。他们使用”BOON”作为静态分析仪,使用”STOBO”作为实验的动态分析器。
Boon是一个静态分析器,它将缓冲区溢出检测问题表述为整数约束问题,并使用简单的图理论知识来解决约束。它更注重可扩展性而不是精度,因此可能会产生误报误报或漏报。
图3.6.1.BOON的结构
STOBO是基于测试技术的动态分析器,它使用小片段访问源代码,这些片段会占用缓冲区并检查库函数的某些安全属性。库函数具有先决条件,例如在 strcpy 函数中分配给目标缓冲区的内存应大于源缓冲区中字符串的长度。如果违反此类条件,则会发生缓冲区溢出,并在跟踪文件中报告警告。但是动态测试需要很多的测试用例。
图3.6.2.STOBO的结构
于是他们做了一个工具同时使用静态分析和动态分析,在静态分析时使用别名变量标记不安全的库函数(如strcpy),并引导动态分析器只关注它们。工具将扫描源代码以查找指针混叠。如果怀疑变量是别名,它将它们标记为可疑变量,因此工具必须足够智能,只能标记那些静态分析器无法精确处理的功能,指定应关注的行号以检测安全漏洞,并为静态分析器生成元数据,用于抑制其生成的虚假警告。然后,假阳性和假阴性的数量总体上有所减少。
图3.6.3.他們的模型
他们模型的性能取决于工具在标记“结构库函数”时的智能程度。C语言足够宽泛,有各种结构,如结构体和联合体。目前,他们的工具还无法智能地处理结构元素(结构)的混叠。
4 未来研究方向
① Findbug是目前流行的一种静态代码分析工具,被下载超过百万次,同时也会产生很多误报,因此深入研究Findbug等静态代码分析工具生成的静态警告的特定警告类型是未来的一种研究方向。如先前文献[23]所示(Khalid等人,2015),Findbug识别的400多种可能的警告类型可分为八类(错误实践、正确性、国际化、恶意代码漏洞、多线程正确性、性能、安全性和危险代码)。可以为这些警告分配优先级(例如,低、中和高),以表明该警告是有效警告或真阳性的警告的把握。
② 目前有效警告识别领域的很多研究是基于Wang等人中提出的黄金集[15]以及黄金特征展开的,使用黄金特征进行机器学习再识别警告有极高的召回率,AUC等,看似效果几乎完美,但是如同Kang等人在[12]中发现的黄金特征仍存在与数据泄漏和数据重复相关的细微缺陷一样,这项发现仍旧存在一些瑕疵有待考究,后续的研究在使用相关结果时也应当对实验结果深入分析,并将研究得出的结果与基线进行比较,得出更准确的结果。因此未来针对黄金集、黄金特征的进一步研究也会是一种方向。
③ 关于Yang等人提出的增量主动学习在识别有效警告领域的应用[16],未来的研究方向之一应该是估计算法停止的时间,过早或过晚停止将导致丢失重要的可操作警告或浪费不必要的运行时间和CPU资源。因此,对算法运行时间以及停止时间的估计,包括需要学习的数据量都需要进行估计,以便用更少的成本达到更高的效率。
④Echer等人在大量证据中发现最初被认为是正确但后来被收回或更正的信息,往往会继续影响记忆和推理[]。进一步可解释为无论是关于持续影响效应的详细资料的具体警告可以成功减少对过时信息的持续依赖,还是通过一个特定的警告与对撤销的信息提供一个貌似合理的替代解释相结合,操作进一步降低CIE,都无法完全消除它。而关于如何在实验中,最大化减少甚至完全消除过往错误对后续的影响,也是未来的研究方向。
⑤在提高跨项目缺陷识别的准确性方面存在一个主要的挑战,即使用一个给定的项目来训练一个模型来识别来自另一个项目的缺陷,而不需要人工检查[28]。如何扩展自动缺陷识别方法,将其用于更多的缺陷模式,如何设计一组可能被大多数缺陷模式充分共享的特征计划利用此模型结合迁移学习方法来自动识别跨项目的缺陷,这将有成为未来可深入钻研之处,有希望能提高跨项目缺陷识别的准确性。
5 结论
在本文中,我们研究了近二十年来关于静态分析工具产生警报中存在的问题和挑战,概述了处理静态分析工具产生的警告的各种方法。我们检索发现了35篇相关论文,在仔细研读这些论文后,我们将这些论文中提出的方法分为了6类,并选择其中一些阐述了具体实现模型。
我们深入研究分析了这6类方法并对针对其要点做出如下总结:机器学习需要足够的数据学习以及合适的方法,警告排序则通过对报警的优先级进行排序并使用警告特征来计算某个警告为有效警告的概率,交互式的方法将合理但不精确的分析与精确但不合理的启发式方法相结合在每轮迭代找到并优化问题,最大化收益。修剪/分类方法则是通过分类的方式,区分警告是可处理还是不可处理,并删除掉不可操作的警告,启发式方法中目前的主流是关闭警告启发式方法,其通过对比不同版本中同一警告的开关情况判断其是否有效,但是其效果不稳定且产生的标签可能与人类预言不符动静态分析结合则是使用动态分析检查静态分析警报是否为真错误,并将检测出故障的测试用例返回给用户。
未来,深入研究Findbug等静态代码分析工具生成的静态警告的特定警告类型、针对黄金集/黄金特征的进一步研究、估计增量注定学习算法停止的时间、研究探索如何最大化减少甚至完全消除过往错误对后续的影响、扩展自动缺陷识别方法都将成为这一领域的可能研究方向,我们计划探索各方法的组合,以更加有效地处理警报。
6 參考文獻
[1]Zhang X, Grigore R, Si X, et al. Effective interactive resolution of static analysis alarms[J]. Proceedings of the ACM on Programming Languages, 2017, 1(OOPSLA): 1-30.
[2]Ruthruff J R, Penix J, Morgenthaler J D, et al. Predicting accurate and actionable static analysis warnings: an experimental approach[C]//Proceedings of the 30th international conference on Software engineering. 2008: 341-350.
[3]Muske T, Talluri R, Serebrenik A. Repositioning of static analysis alarms[C]//Proceedings of the 27th ACM SIGSOFT international symposium on software testing and analysis. 2018: 187-197.
[4]Akremi A. Software security static analysis false alerts handling approaches[J]. International Journal of Advanced Computer Science and Applications, 2021, 12(11): 702-711.
[5]Querel L P, Rigby P C. Warningsguru: Integrating statistical bug models with static analysis to provide timely and specific bug warnings[C]//Proceedings of the 2018 26th ACM Joint Meeting on European Software Engineering Conference and Symposium on the Foundations of Software Engineering. 2018: 892-895.
[6]Muske T, Serebrenik A. Techniques for Efficient Automated Elimination of False Positives[C]//2020 IEEE 20th International Working Conference on Source Code Analysis and Manipulation (SCAM). IEEE, 2020: 259-263.
[7]Aggarwal A, Jalote P. Integrating static and dynamic analysis for detecting vulnerabilities[C]//30th Annual International Computer Software and Applications Conference (COMPSAC’06). IEEE, 2006, 1: 343-350.
[8]Gosain A, Sharma G. A survey of dynamic program analysis techniques and tools[C]//Proceedings of the 3rd International Conference on Frontiers of Intelligent Computing: Theory and Applications (FICTA) 2014. Springer, Cham, 2015: 113-122.
[9]Bayer U, Moser A, Kruegel C, et al. Dynamic analysis of malicious code[J]. Journal in Computer Virology, 2006, 2(1): 67-77.
[10]Kirchmayr W, Moser M, Nocke L, et al. Integration of static and dynamic code analysis for understanding legacy source code[C]//2016 IEEE international conference on software maintenance and evolution (ICSME). IEEE, 2016: 543-552.
[11]Xueqi Yang , Jianfeng Chen, Rahul Yedida, Zhe Yu, Tim Menzies. Learning to recognize actionable static code warnings(is intrinsically easy) . Empirical Software Engineering (2021) 26: 56
[12]Hong Jin Kang, Khai Loong Aw, David Lo. Detecting false alarms from automatic static analysis tools: how far are we?. 2022 IEEE/ACM 44th International Conference on Software Engineering (ICSE)
[13]Hegedus, P., & Ferenc, R. (2022). Static code analysis alarms filtering reloaded: A new real-world dataset and its ML-based utilization. IEEE Access, 10, 55090–55101.
[14]Muske, T., & Serebrenik, A. (2016). Survey of approaches for handling static analysis alarms. 2016 IEEE 16th International Working Conference on Source Code Analysis and Manipulation (SCAM), 157–166
[15]Wang, J., Wang, S., & Wang, Q. (2018). Is there a “golden” feature set for static warning identification? Proceedings of the 12th ACM/IEEE International Symposium on Empirical Software Engineering and Measurement, 2018,17, 1–10.
[16]Yang, X., Yu, Z., Wang, J., & Menzies, T. (2021). Understanding static code warnings: An incremental AI approach. Expert Systems with Applications, 167. 2020
[17]T. Hall, S. Beecham, D. Bowes, D. Gray, and S. Counsell. 2012. A Systematic
Literature Review on Fault Prediction Performance in Software Engineering. IEEE Transactions on Software Engineering 38, 6 (Nov 2012), 1276–1304.
[18] Mingshuang Qing, Xiang Feng, Jun Luo, Wanmin Huang, Jingui Zhang, Ping Wang, Yong Fan Xiuting Ge, Ya Pan.A machine learning-based static analysis warning prioritization. 2021 IEEE 21st International Conference on Software Quality, Reliability and Security Companion (QRS-C)QRS-C55045.2021.00103
[19] B. H. Dang, “A practical approach for ranking software warnings from multiple static code analysis reports,” in 2020 SoutheastCon, vol. 2. IEEE, 2020, pp. 1–7
[20] X. Yang, J. Chen, R. Yedida, Z. Yu, and T. Menzies, “Learning to recognize actionable static code warnings (is intrinsically easy),” Empirical Software Engineering, vol. 26, no. 3, pp. 1–24, 2021.
[21] S. Heckman and L. Williams, “A model building process for identifying actionable static analysis alerts,” in 2009 International Conference on Software Testing Verification and Validation. IEEE, 2009, pp. 161–170.
[22] J. Ruthruff, J. Penix, J. Morgenthaler, S. Elbaum, and G. Rothermel, “Predicting accurate and actionable static analysis warnings,” in 2008 ACM/IEEE 30th International Conference on Software Engineering. IEEE, 2008, pp. 341–350.
[23]Khalid H, Nagappan M, Hassan AE (2015) Examining the relationship between findbugs warnings and app ratings. IEEE Software 33(4):34–39
[24]Yuwei Zhang, Ying Xing, Yunzhan Gong, Dahai Jin, Honghui Li, Feng Liu. A variable-level automated defect identification model based on machine learning. Soft Computing (2020) 24:1045–1061
[25] Athos Ribeiro, Paulo Meirelles, Nelson Lago, Fabio Kon. Ranking Warnings from Multiple Source Code Static Analyzers via Ensemble Learning. the 15th International Symposium, · August 2019
[26] Diego Marcilio , Carlo A. Furia , Rodrigo Bonifácio , Gustavo Pinto. SpongeBugs: Automatically Generating Fix Suggestions in Response to Static Code Analysis Warnings. Preprint submitted to Elsevier June 3, 2020
[27] ULLRICH K. H. ECKER, STEPHAN LEWANDOWSKY, AND DAVID T. W. TANG. Explicit warnings reduce but do not eliminate the continued influence of misinformation. Memory & Cognition 2010, 38 (8), 1087-1100
[28] Jung Y, Kim J, Shin J, Yi K (2005) Taming false alarms from a domainunaware c analyzer by a Bayesian statistical post analysis. In: Proceedings of the 12th international static analysis symposium, pp 203–217
[29a] Kim S, Ernst MD (2007a) Prioritizing warning categories by analyzing software history. In: Proceedings of the 4th international workshop on mining software repositories, pp 27–27
[29b] Kim S, Ernst MD (2007b) Which warnings should i fix first? In: Proceedings of the 2007 joint meeting on foundations of software engineering, pp 45–54
[30] Williams CC, Hollingsworth JK (2005) Automatic mining of source code repositories to improve bug finding techniques. IEEE Trans Softw Eng 31(6):466–480
[31] Kremenek T, Ashcraft K, Yang JF, Engler DR (2004) Correlation exploitation in error ranking. In: Proceedings of the 12th ACM SIGSOFT international symposium on foundations of software engineering, pp 83–93
[32] Ayewah N, Pugh W, Morgenthaler JD, Penix J, Zhou YQ (2007) Evaluating static analysis defect warnings on production software. In: Proceedings of the 7th ACM SIGPLAN-SIGSOFT workshop on program analysis for software tools and engineering, pp 1–8
[33] Ruthruff JR, Penix J,Morgenthaler JD, Elbaum SG, Rothermel G (2008) Predicting accurate and actionable static analysis warnings: an experimental approach. In: Proceedings of the 30th international conference on software engineering, pp 341–350
[34] Hanam Q, Tan L, Holmes R, Lam P (2014) Finding patterns in static analysis alerts: improving actionable alert ranking. In: Proceedings of the 11th working conference on mining software repositories, pp 152–161
[35] Flynn L, Snavely W, Svoboda D, VanHoudnos NM, Qin R, Burns J, Zubrow D, Stoddard R, Marce-Santurio G (2018) Prioritizing alerts from multiple static analysis tools, using classification models. In: Proceedings of the 1st international workshop on software qualities and their dependencies, pp 13–20