大语言模型时代的自动化缺陷生成

互联不一般哥 2024-06-06 12:40:53

Automated Bug Generation in the era of Large Language Models

Ibrahimzada, Ali Reza1, Chen Yang1, Ryan Rong2, Reyhaneh Jabbarvand1

1University of Illinois Urbana-Champaign, USA

2The Peddie School, USA

引用

Ibrahimzada A R, Chen Y, Rong R, et al. Automated Bug Generation in the era of Large Language Models[J]. arXiv preprint arXiv:2310.02407, 2023.

论文:https://arxiv.org/abs/2310.02407

仓库:https://github.com/projectinvestigator/BUGFARM

摘要

在软件工程中,检测、定位和修复软件系统中的缺陷技术是至关重要的。这些技术的效果评估需要复杂的缺陷,即那些通过测试难以检测和通过调试难以修复的缺陷。本文提出了缺陷生成技术BugFarm,用于将任意代码转换成多个复杂缺陷。BugFarm利用大语言模型(LLMs)在多个位置变异代码(难以修复)。为了确保多次修改不显著改变代码的表示,BugMarm分析底层模型的注意力,并指导LLMs只改变最少关注的位置(难以检测)。BugFarm非常高效,即它在不需要任何事先训练的情况下变异代码仅需九秒钟。

1 引言

机器学习正在成为新的自动化技术,软件工程自动化也不例外。例如Copilot等 AI 对编程技术已集成到IDE中,而如GPT-4和Bard等大语言模型(LLMs)现在可以通过 API 访问。遵循这一趋势,最先进的软件分析技术要么对预训练的代码语言模型进行微调,要么提示 LLMs 自动执行与代码相关的任务。这需要自动化技术生成高质量数据集以评估其真正的效果。关于与缺陷相关的任务,如缺陷预测、定位和修复,这些数据集应包括一系列复杂的缺陷,即那些难以检测以挑战缺陷预测技术和难以修复以用于调试方法的缺陷。

从传统软件工程的角度来看,难以检测的缺陷通常存在于只有在特定测试输入或边缘情况组合下才可达的位置。相似的定义不适用于基于学习的缺陷预测技术。这是因为它们不关心什么输入触发了给定代码中的缺陷。相比之下,它们在训练/微调数据中寻找缺陷模式,或检查代码表示是接近它们见过的错误还是正确的示例。因此,要挑战基于学习的缺陷预测技术,应注入未见过的缺陷模式,使得生成的缺陷和正确代码的代码表示相似。难以修复的缺陷通常涉及多个语句,使得调试技术难以定位和理解它们的交互以自动修复它们。从基于学习的软件工程的角度看,一个类似的定义是有效的,但需稍加考虑:机器学习的力量在于从其数据集中持续存在的模式中学习。因此,在多个位置修改代码,其中基于学习的调试技术特别寻找定位或修复缺陷的位置,将是违反直觉的。现有技术是否能提供如定义的复杂缺陷,以评估基于学习的技术?

已有几次尝试构建真实世界缺陷数据集,例如 Defects4J、BugSwarm、BugsInPy、RegMiner和 ManySStuBs4J。虽然这些数据集代表了现实世界中的缺陷,但它们仅限于它们挖掘努力中包含的项目和缺陷模式。更重要的是,它们可能被包含在基于学习的技术的训练/微调数据中,导致数据泄露。为了克服这些限制,研究人员提出了自动缺陷生成技术。这些技术默认改变代码中的几个位置(易于修复和检测),但可以配置为修改多行。尽管如此,随机改变多行或遵循一组启发式规则可能会导致突变体与正确代码的代码表示不同,使它们易于检测。此外,改变基于学习的修复技术已经训练用于查看和修复的行,如条件语句,会产生容易修复的缺陷,即使它们涉及多行。

提出的解决方案。为了推进自动化缺陷生成技术在评估基于学习的与缺陷相关任务方面的应用,我们提出了 BugFarm。对于给定的任意代码,BugFarm提示大语言模型(LLM)突变多个语句。鉴于 LLM 在生成任务中可能具有创造性,利用它们有助于避免对有限数量的突变操作符和缺陷模式的过度拟合。为了确保改变过多的位置不会极大地改变突变体的代码表示,BugFarm 分析底层模型的关注点,并指示 LLM 只改变模型最少关注的那些位置。因此,生成的代码与原始代码具有相似的表示,但在多个位置有所不同。这使得它们难以被缺陷预测方法检测,并且难以被调试技术修复。BugFarm 是编程语言无关的,即使它成为生成任何编程语言缺陷的实用方法。与相关的突变生成技术一样,BugFarm 创建的是未经证实的缺陷,应通过测试执行进行验证。本文的显著贡献包括:

本文提出了一种针对评估基于学习的与缺陷相关任务的新型缺陷生成技术。BugFarm,依赖于模型对代码不同部分的关注来确定在哪里注入缺陷,以便对代码表示的影响最小化。它利用这种信息来为大语言模型(LLM)制定上下文提示,以突变任意代码。BugFarm的实现和工件,包括所有生成的缺陷,都已公开可用。本文对BugFarm以及两种最新的基于学习的缺陷生成方法LEAM和 BERT进行了广泛评估。我们对15个Java项目生成的320k+个缺陷(来自超过2.5M个突变体)的评估回答了与(1)生成缺陷的属性,(2)基于学习的缺陷预测模型检测它们的能力,(3)基于学习的程序修复技术修复它们的效果,(4)提示制作的影响,以及(5)技术的性能特征相关的研究问题。结果证实,BugFarm生成的缺陷难以检测(假阴性率高达41%,准确率、精度、召回率和F1分数分别低11%,6%,29%和21%)和难以修复(与LEAM和BERT缺陷的34%和49%的修复成功率相比,修复成功率为22%)。此外,使用BugFarm生成有效的缺陷更加高效。

2 示例说明

为了阐述以往工作的局限性和介绍 BugFarm 背后的核心理念,我们将使用图1中的代码片段。图1a中的原始代码接受 bag 和 transformer 对象作为输入。如果 bag 不为空,它会将内部的所有对象转移到 transformer 中。通过增加、删除或修改其主体中的13个语句(为了更好的展示,一些语句被拆分为两行),可以以多种方式向这段代码注入缺陷。这些缺陷旨在挑战我们在评估中使用的缺陷预测和程序修复模型,这些模型在CodeT5的基础上进行了微调。关于底层模型对原始代码的关注,两个关注度最低的语句(算法1中的详细信息)用绿色突出显示。

我们利用三种缺陷生成工具,即 BugFarm、LEAM和 BERT,将原始代码片段转换为缺陷(缺陷通过测试执行得到确认)。LEAM 是一种将代码表示为AST节点序列并学习应用语法规则以选择和修改代码以生成缺陷的技术。BERT 选择与AST节点对应的代码标记,用特殊标记 <mask> 替换它们,并请求CodeBERT用新的标记替换它们以生成缺陷。BugFarm 识别关注度最低的语句,并提示一个LLM只对这些行进行引发缺陷的转换。图1b和1c展示了 LEAM 和 BERT 生成的一个缺陷(LEAM和BERT 分别生成了 19 和 68 个突变体,其中只有6和1个被确认为缺陷)。BugFarm 生成的缺陷显示在图1d中。引入缺陷的行用红色突出显示。

BugFarm 的缺陷从多个角度来看都很显著。首先,它涉及多个语句(难以定位和修复)。其次,两个修改的语句都是关注度最低的语句之一,这使得模型难以区分原始代码和缺陷(难以检测)。LEAM 和 BERT 的缺陷只修改了一个不是关注度最低的语句。因此,当使用我们研究的缺陷预测模型和程序修复模型运行时,它们很容易被检测和修复。相比之下,同样的模型未能检测和修复 BugFarm 的缺陷。

图1:示意图展示了使用 LEAM (b)、BERT (c) 和 BugFarm (d) 为原始代码 (a) 生成的缺陷

3 BugFarm方法

3.1 方法概述

图2提供了BugFarm框架的概览,该框架由三个主要组成部分构成:(1)方法提取器,(2)关注分析器,和(3)缺陷生成器。BugFarm接受一个项目和一个预训练的代码语言模型作为输入,并通过轻量级静态分析提取方法。对于每个方法,它通过分析模型对各个代码标记的关注来识别缺陷位置候选。为了为每个方法生成缺陷,BugFarm会为一个大语言模型(LLM)设计一个提示,包括要转换成缺陷的代码和反映缺陷注入候选位置的额外上下文。从生成的缺陷中,BugFarm选择那些语法上正确的缺陷,其中引入缺陷的变化不会显著改变模型的关注。方法提取器组件接受输入项目并构建其对应的解析树以提取源文件中的所有方法。这些方法将作为输入传递给关注分析器,以识别缺陷注入的候选位置。

由于代码的自然性和此类模型在自然语言处理(NLP)中的有希望的结果,最近的最先进的基于学习的软件工程模型均基于变换器。基于变换器的模型依赖于关注以进行神经代码表示。因此,为了识别向给定方法注入不显眼缺陷的候选位置,关注分析器提取模型对代码标记的相应关注,并识别那些在代码表示中贡献较低的标记,即那些关注权重值较小的标记。BugFarm中的缺陷位置位于语句级别;因此,BugFarm根据#TLA/#T值对输入方法的语句进行排序,并选择值最低的语句。这里,TLA是最少关注的标记数量,T表示语句中标记的总数。

图2:BugFarm概览

最后,缺陷生成器组件接受缺陷位置候选列表作为输入,并创建一个由自然语言指令、缺陷位置候选和方法组成的提示。然后它将提示发送给一个LLM,并收集响应中生成的缺陷。对于LLM生成的缺陷,BugFarm计算引发缺陷的变化对模型对有缺陷方法的关注的影响与输入方法相比,并选择那些对关注影响微不足道的缺陷。它还将语法不正确的缺陷丢弃,以保证质量。

3.2 方法提取器

我们的方法与大多数依赖于缺陷数据集进行自动缺陷生成的先前工作不同。相反,它专注于使用大语言模型(LLM)将多样化和复杂的缺陷注入任何维护良好的项目中,不论编程语言如何。因此,我们假设 BugFarm 的输入是一个项目而不是单一方法。作为第一步,BugFarm 首先需要提取每个输入项目中实现的方法。为此,方法提取器组件利用特定于语言的解析器(取决于输入项目中使用的编程语言),构建程序解析树,并提取方法和构造函数的列表。接下来,它使用解析树中的 MethodDeclaration 和 ConstructorDeclaration 块收集签名和主体(不包括文档字符串)。每个方法将传递给关注分析器组件,我们接下来将对此进行描述。

3.3 关注分析器

基于变换器架构的最新代码语言模型包括一个编码器来捕捉输入的上下文表示和一个解码器来生成输出标记。为了生成一系列标记的上下文化向量表示,变换器依赖于多头自注意力(Multi-Head Self-Attention)。更具体地说,对于由 n个标记组成的方法 −−→Tkn = {m0, . . . ,mn−1},具有 L 层的变换器模型将 −−→Tkn 作为输入并生成 Hℓ = [hℓ0, ..., hℓn−1]。这里,Hℓ 对应于层 ℓ ∈ {1, 2, ..., L} 中的隐藏向量表示。在每一个变换器层 ℓ 中,使用多个自注意力头来聚合前一层的输出。因此,对于方法中的每个标记mi,自注意力会分配一组与输入序列中所有其他标记的关注权重,即 Attention(mi) = {ai0, . . . , ain−1},其中aij表示mi 对mj 的相对关注。

算法1

变换器的隐藏表示权重将基于关注权重计算,使关注权重成为确定方法最终表示中每个标记重要性的关键。最近的研究表明,关注分析可以用来解释训练期间学到的知识。遵循这些见解,BugFarm利用自注意力权重分析来审查输入方法并识别关注权重最低的标记(随后是语句)。这些语句是 BugFarm 可以在不影响方法整体表示的情况下进行缺陷诱导转换的地方。算法 1 解释了我们的关注分析方法,它将要转换成缺陷的方法、阈值 k 和基于变换器的模型作为输入,并确定输出为最少关注语句 LAS 的 k%。为此,它首先提取方法中关注度最低的标记列表LAT(第 1-10 行)并使用它们来确定关注度最低的语句LAS(第 11-20 行)。

该算法首先识别给定方法中的标记 −−→Tkn 和语句 −−→Smt,并初始化 LAT 和 LAS 变量为空(第1-3行)。接下来,它查询模型 M 以提取自注意力值(第4行)。对于一个有 L 层和每层 H 个注意力头的模型 M,注意力值将在头和层之间平均,得到一个 n × n 矩阵,其中 n 是标记的数量。对于方法中的每个标记mi,算法进一步平均相对于其他标记的注意力权重(在自注意力矩阵的每列中平均值),为方法中的每个标记mi 计算单一的注意力权重值(第5行)。鉴于我们对代码中 关注度最低的标记感兴趣,算法1排序注意力权重向量 −−−−−−−−−→TknAttnW,填充它们相应的索引到 −−−−−−−−−−−−→SortedTknInd(第6行),并识别出关注度最低的顶部 k% 的标记,LAT(第7-10行)。

提取出关注度最低的标记后,算法可以识别关注度最低的语句,LAT。为此,它通过一个得分(第11-14行)为每个语句赋权,该得分是该语句中关注度最低的标记数量与其长度的比率。这里的关键思想是,一个在关注度最低的标记之间有最高重叠量的语句应该获得较低的得分,因此,被认为是关注度最低的语句。如果不对语句长度进行标准化,较长的语句将被处罚,BugFarm永远不会选择它们作为缺陷注入位置。最后,根据它们的得分,语句按升序排序,关注度最低的 k% 的语句(如果 k% 的总语句数少于一个,我们取上限)将作为 LAS 返回(第15-20行)。

3.3 缺陷生成器

缺陷生成涉及修改、添加或删除原始方法中的代码段,以改变程序的预期行为。BugFarm 的缺陷生成模块将方法及其在上一步骤中确定的 LAS 集合作为输入,并设计大语言模型(LLM)提示,生成方法的 N个有缺陷版本作为输出。我们让 BugFarm 可配置的直觉是,我们的缺陷很可能将用作与缺陷相关任务的训练/微调数据。因此,为单一方法生成多个有缺陷版本将有助于模型更容易区分有缺陷代码和无缺陷代码。然而,缺陷的总数还取决于方法的大小和阈值 k。例如,对于少于 10 个语句的方法,k = 10% 返回一个作为 LAS 的语叧,以 N 种独特方式改变该语句可能是不可行的。

BugFarm 的提示由三部分组成。第一部分是自然语言指令,要求 LLM 生成缺陷。第二部分提供有关在何处注入缺陷的上下文信息,即只考虑关注度最低的语句,LAS,以进行引发缺陷的更改。最后,我们在提示中包括整个方法,包括签名和方法体。这样的提示是 LLM 不可知的,即它们可以与各种现有的 LLM 一起使用,如 LLaMa、PaLM、Copilot、Alpaca和 ChatGPT。唯一需要考虑的是检查提示的大小是否与 LLM 的上下文窗口匹配。在 LLM 对提示做出响应后,缺陷生成器组件验证(1)它们是否语法正确以及(2)更改是否不影响模型的关注。未通过这两项检查的响应将被丢弃。理想情况下,我们希望产生的缺陷是语法正确的。为此,我们的提示还包括生成语法正确代码的指令。然而,我们的实验表明,尽管要求 LLM 生成特定于较长方法的语法正确代码,它生成的响应可能是不可解析的。此外,我们的目标是生成与原始代码有非常接近的神经表示的缺陷。因此,我们评估模型对生成的缺陷的关注,并且只有当更改仍然属于最少关注的语句时才接受它们。

算法2

算法 2 展示了 BugFarm 的缺陷生成和验证方法。它首先初始化输出变量 Bug(第 1 行),并获取method中 LASs 的索引(第 2 行)。接下来,在 method 中的每个语句添加一个索引(第 3 行)。这将有助于我们通过编号而不是包含整个语句来引用 LASs,从而减少提示的大小。这对于较长的方法或语句尤其重要,因为 LLM 的上下文窗口是有限的。接下来,我们将使用所需的上下文,即索引的方法和缺陷注入位置,制作提示并将提示发送给 LLM(第 4-5 行)。最后,一旦 LLM 做出响应,我们检查生成的缺陷是否语法正确(第 7-8 行),以及更改的语句是否为模型关注度最低的语句(第 9-14 行),将其添加到可接受的缺陷集中(第 15-16 行)。

4 实验评估

4.1 实验设置

研究问题。为了评估 BugFarm 的有效性,我们将其与两种最先进的自动缺陷生成方法进行比较,即 LEAM 和 BERT,研究以下研究问题:

RQ1:生成缺陷的特征。BugFarm 能否成功向任意代码注入缺陷?每种方法生成的缺陷具有什么特征?我们的缺陷在多大程度上与其他方法生成的缺陷重叠?

RQ2:生成难以检测的缺陷的效果如何。与其他技术相比,基于学习的缺陷预测模型在检测 BugFarm 缺陷方面表现如何?

RQ3:生成难以修复的缺陷的效果如何。与其他方法生成的缺陷相比,基于学习的自动程序修复(APR)技术能够修复 BugFarm 缺陷到什么程度?

RQ4:提示工程的必要性。在 BugFarm 中进行提示工程的好处是什么?

RQ5:性能。使用 BugFarm 和其他方法生成和验证缺陷需要多长时间?

基线方法。我们将 BugFarm 与两种最新的突变生成技术 BERT 和 LEAM 进行比较。为了注入突变体,BERT 选择代表程序行为的 AST 节点,包括文字、标识符、表达式、赋值、对象字段、方法调用、数组访问和类型。然后,它用特殊令牌 <mask> 替换所选 AST 节点中的标记,并使用 CodeBERT 预测被屏蔽的标记。其基本思想是,如果 CodeBERT 预测的标记与原始标记不同,则转换引入了一个缺陷。LEAM 是一种基于深度学习的技术,它从大量实际世界缺陷的示例中学习突变代码。为此,他们将代码表示为 AST 节点序列,并学习应用八个语法规则来选择和修改代码。与经典方法 PIT和 Major相比,BERT 和 LEAM 都声称生成更好的缺陷(通过测试执行确认的突变)。因此,我们在评估中没有包含经典技术。 对于 BugFarm,我们使用了阈值 k= 10%,主要是因为备选方法在给定代码中不会更改超过少数语句。本节其余部分的实验结果证实,即使使用如此低的阈值,我们仍然超越了其他技术。我们预计较高的阈值将使我们的缺陷与其他方法相比更复杂,从而提高了边界。我们还配置了 BugFarm,使其每个方法最多生成三个突变体(在算法 2 中的 N = 3),因为预算允许。BugFarm 的当前实现中的 Bug Generator 组件使用 GPT-3.5-turbo 作为 LLM,因为它在大量模型中优越并具有成本效益。使用更先进的 LLM,如 GPT-4,可能会产生更好的结果,而不是更差的结果。

评估指标。本评估指标。为了比较缺陷预测模型的性能,我们使用准确率、精确率、召回率、F1 分数、误报率(FPR)和漏报率(FNR)作为我们的度量标准。为了评估自动程序修复(APR)结果,我们衡量修复成功率,即技术成功修复的缺陷数量。我们将 TP、TN、FP 和 FN 定义如下:真正例(True Positive,TP)。代码有缺陷,模型预测为有缺陷。真负例(True Negative,TN)。代码没有缺陷,模型预测为没有缺陷。假正例(False Positive,FP)。代码没有缺陷,模型预测为有缺陷。假负例(False Negative,FN)。代码有缺陷,模型预测为没有缺陷。

RQ1 生成的缺陷质量

为了回答这个研究问题,我们使用下面列出的指标比较了BugFarm生成的缺陷与其他替代方法生成的缺陷的特征。这些指标是针对所有方法计算的,并对每个项目进行了平均。对于BugFarm,我们还将所有模型(CodeBERT、CodeT5和NatGen)的数字进行了平均。

未确认的缺陷数量:该指标在表格1的UB列下计算,显示了每个项目生成的未确认的缺陷/突变体的总数。所有方法都成功地为主题项目中的所有方法生成了突变体/缺陷。与LEAM和BugFarm相比,BERT生成的缺陷数量多1.5倍和8倍。

确认的缺陷数量:该指标在表格1的CB列下显示,表示不同方法生成的每个项目的确认的缺陷数量。括号内的数字表示与未确认的缺陷数量相比的确认的缺陷的百分比。较高的百分比暗示了技术在缺陷生成方面的优越性,即代码变换更可能是缺陷。从这些结果中,我们可以看到BugFarm生成的缺陷中有37%是真实的缺陷,而LEAM和BERT分别为20%和16%。除了一个项目(Commons Compress)外,BugFarm的#CB/#UB比率更高,而且差距明显。

参与缺陷生成的语句数量:该指标表示生成缺陷所涉及的添加、删除或修改的语句数量。平均而言,即使使用k = 10%的阈值,BugFarm相比LEAM和BERT更改更多的语句以生成缺陷。虽然#SI对于BugFarm的缺陷更高,但考虑到这些语句是最不受关注的语句,我们将在稍后看到,模型将更难以将它们与正确的代码区分开。

删除的行数:删除整个语句虽然可能会创建一个缺陷,但这可能不是最好的引入缺陷的转换,因为它会显著改变注意力,导致运行时异常而不是语义缺陷。因此,我们还想从这个方面比较生成的缺陷。表格1中的LD列显示了在生成缺陷过程中仅删除(或注释)行的缺陷的百分比。与LEAM(13%)和BERT(0.02%)相比,BugFarm在生成缺陷过程中不删除(或注释)任何语句(所有项目的平均值为0%)。

编辑距离:我们还想比较每种技术生成的原始版本和有缺陷版本之间的编辑距离。我们使用Levenshtein编辑距离,它度量了将一个字符串变成另一个字符串所需的最小单字符编辑(插入、删除或替换)数量。每个代码被表示为字符字符串,以计算Levenshtein编辑距离。表1中ED列的结果是通过#CB归一化的编辑距离。与LEAM和BERT相比,BugFarm的缺陷具有更高的ED值。这再次表明,BugFarm对代码的更改更大但更不显眼,正如我们将在RQ2和RQ3中展示的那样。在BERT和LEAM之间,后者生成的缺陷在原始代码中的不同位置更多。

独特性:最后,我们对我们的缺陷与BERT和LEAM生成的缺陷有多少重叠感兴趣。为此,我们测量了BugFarm生成的每个缺陷与BERT和LEAM生成的所有对应缺陷之间的精确匹配(EM)和CodeBLEU值。例如,对于给定的方法A,如果BugFarm生成了三个缺陷b1,b2,b3,而LEAM生成了四个,,,,我们构造了12个⟨bi,⟩对来计算EM和CodeBLEU。EM是一个严格的全有或全无的度量;只要错一个字符,分数就是0。如果bi的字符与bj的字符完全匹配,则对对应的EM = 1;否则,EM = 0。

表1:比较BugFarm、BERT和LEAM生成的缺陷的特征

总结。表1中的EM和CodeBLUE值显示在列OL(与LEAM的重叠)和OM(与BERT的重叠)下。第一个数字表示EM,第二个数字是CodeBLEU。这些数字显示,Ibrahimzada等人生成的所有项目的BugFarm生成的总缺陷中,仅有7%和3.49%分别与LEAM和BERT重叠,证实了BugFarm缺陷的独特性。平均CodeBLEU值也分别为0.67和0.75。对于CodeBLEU的高值在这里并不构成威胁,考虑到缺陷转换与原始代码相比并没有大的改变。事实上,这表明虽然BugFarm的缺陷更能挑战基于学习的技术,但它们在语义上与LEAM和BERT的缺陷相似;在评估的任务中可能与它们一样有效。

RQ2 检索模型性能比较

在这个研究问题中,我们调查了与替代方法相比,BugFarm缺陷预测模型的有效性。鉴于讨论的现有模型不可用的情况,我们使用了真实世界和合成缺陷来对三个预训练的代码语言模型(CodeBERT、CodeT5和NatGen)进行微调。我们采用了微调Transformer模型的最佳实践,并在微调、验证和测试缺陷预测模型中使用了相同的类分布。所有模型在最多10个epochs内进行微调,采用了基于损失的早停策略,连续两个epochs的验证误差最小的模型被选为实验中的模型。为了更可靠的结果,我们重复了10次评估,并报告了平均值。通常,应该在每个微调的模型上运行BugFarm以相应地生成缺陷。然而,我们的调查显示,微调并不会极大地影响最低出现注意力的集合。这与先前工作的发现一致,即微调只会改变最后几层的注意力,而不会影响模型的整体注意力。它还表明,本研究中生成的许多BugFarm缺陷是其他研究人员可以重复使用的。因此,我们只为每个模型的方法生成了缺陷,这些方法的LAS集与基线预训练模型相比发生了变化。

表2. 在预测合成漏洞方面研究的经过微调的模型的有效性。每个不同的行集显示了相同的预训练模型,该模型经过相同的数据集微调,但在不同的漏洞数据集上进行了测试。

在合成缺陷上的微调。我们对三个基线预训练模型进行了在LEAM和BERT缺陷上的微调。这为我们提供了六个经过微调的缺陷预测模型,即BERT-CodeBERT、BERT-CodeT5、BERT-NatGen、LEAM-CodeBERT、LEAM-CodeT5和LEAM-NatGen。我们的目标不仅是评估这些模型在预测BugFarm缺陷方面的表现,还要看BugFarm缺陷相对于其他技术有多难被检测到。为此,我们对经过微调的缺陷预测模型进行了对BugFarm和其他方法的评估,而其他方法的缺陷没有用于微调。例如,我们对由BugFarm和LEAM生成的缺陷评估BERT-CodeBERT。为了确保公平比较,我们考虑了每个项目的方法,这些方法都由两种比较技术生成了已确认的缺陷。这将导致两种技术的FPR值相同,但可以让我们更好地评估模型的有效性。从安全的角度来看,漏掉一个缺陷/漏洞比将正确的代码标记为有缺陷更严重。 表2的第1–12行显示了此实验的结果。对于准确率、精确度、召回率和F1得分,较低的指标值表示该方法的优越性(缺陷更难与正确代码区分开来,因此更容易被检测到)。对于FNR,较高的指标值表示缺陷更难以检测到。从这些结果中,我们可以清楚地看到,BugFarm缺陷始终实现了更高的FNR值(平均边际为23%(最小=2.76%,最大=40.89%))和更低的其他指标值(准确率的平均边际=5.97%,精确度的平均边际=1.48%,召回率的平均边际=15.5%,F1得分的平均边际=10.78%)。此外,通过观察F1得分值,我们发现在LEAM上微调的模型比在BERT上微调的模型更难检测到BugFarm缺陷。我们认为这是因为BERT缺陷更加多样化,因为它改变了代码的许多标记并通过波束搜索将它们组合起来,而LEAM缺陷试图模仿他们从GitHub问题跟踪器中获取的数据集中的缺陷。

在真实世界的缺陷上进行微调。为了避免基于合成缺陷的结论中的任何偏见,我们还使用三个数据集,即Defects4J、BugSwarm和RegMiner,对基线预训练模型进行了真实世界的缺陷微调。真实世界的评估数据集包含了来自Defects4J、BugSwarm和RegMiner的723、3285和36412个原始和有缺陷的方法,分别。这导致了三个缺陷预测模型,即REAL-CodeBERT、REAL-CodeT5和REAL-NatGen。我们对每个模型在BugFarm、BERT和LEAM缺陷上进行了评估。表2的第13-21行显示了这个实验的结果,边际表示与次优合成缺陷数据集的差异。这些结果显示了我们观察到的与合成缺陷微调的模型相似的趋势,即BugFarm缺陷导致更高的FNR(平均为54.35%)和更低的准确率(平均为50.86%)、精确度(平均为51.52%)、召回率(平均为45.64%)和F1得分(平均为47.34%)值。 我们还可以看到,与在合成缺陷上进行微调的模型相比,在所有指标上,对真实世界的缺陷进行微调的模型表现不佳。对于这一观察结果的一个可能解释是真实世界的缺陷(用于微调)与合成缺陷(用于测试)之间的分布偏移。这种分布偏移的两个根本原因是:(1)真实世界的缺陷属于与我们生成合成缺陷的项目不同的项目;(2)真实世界的缺陷的性质不同于合成缺陷。特别是对于BugFarm和BERT,缺陷生成的目标不包括任何与真实世界缺陷的相似性。

总结:无论是来自合成数据集还是真实世界的漏洞数据集,漏洞预测模型都更难检测到 BugFarm 生成的漏洞,而不是其他合成漏洞。

RQ3 难以修复漏洞的有效性

表3:FitRepair 在修复合成漏洞方面的有效性

要进一步展示我们的漏洞的复杂性,我们评估了FitRepair在修复BugFarm、BERT和LEAM漏洞方面的能力。FitRepair的默认配置旨在为单个漏洞生成5000个补丁,并在超过五个小时后终止。考虑到我们主题漏洞的规模和可观的补丁验证时间,我们将最大补丁数减少到了1007(由FitRepair的开发人员确认,这不会导致性能显著下降),并对从每个漏洞数据集中抽样的100个漏洞进行了评估。在抽样时,我们控制了选择所有方法中相同的漏洞。为了选择方法,我们根据方法大小(以字符数为单位)的降序对它们进行排序,并选择了前100个。我们的理由是,当方法更长时,漏洞注入的潜在位置增加。因此,观察到由每种技术产生的不同漏洞的可能性更高。收集的漏洞来自15个主题项目中的11个。

表3的第一行显示了生成的漏洞的分布,根据漏洞生成中涉及的语句数量(#SI来自RQ1)。大多数来自LEAM和BERT的主题漏洞与原始代码只有一行的不同,而就这个指标而言,BugFarm的漏洞更为多样化。每个漏洞数据集生成35个补丁,平均需要两到七个小时。我们验证了每个漏洞生成的所有补丁,如果其中一个补丁导致了绿色测试套件,则忽略其他补丁,并将漏洞视为由FitRepair修复。表3的第二行显示了FitRepair成功修复的漏洞的百分比。

FitRepair成功修复了34%和49%的LEAM和BERT漏洞,分别。相反,它只能修复BugFarm漏洞的27%,22%和23%。这并不令人惊讶,因为已知APR技术在修复SI=1的漏洞时表现更好。事实上,对于BERT和LEAM的正确补丁,只与相应的漏洞在一行上有不同。对于BugFarm,这个值只有64%,这意味着与替代方法相比,BugFarm的一行漏洞的复杂性更高。我们对漏洞性质的更深入调查显示,LEAM和BERT漏洞主要更改条件/分支语句。由于FitRepair的修复模板专门设计用于修复条件/分支语句中的漏洞(if语句中的逻辑表达式),因此它可以更好地修复LEAM和BERT漏洞。相反,由于LLM在代码合成方面的强大功能,BugFarm在引入漏洞注入方面更具创造性,并且考虑到模型关注度较低的位置进行漏洞注入。因此,它可以挑战专门设计用于修复已知漏洞模式的基于学习的APR技术。通过查看修复了SI>=2的漏洞的其他补丁,我们观察到了相同的模式,即至少有一个语句更改了条件语句。

总结。与替代方法相比,当应用于相同的方法时,BugFarm生成的漏洞更难被基于学习的修复技术修复。当方法更长时,BugFarm的威力将变得更加明显,因为它可以改变方法中的多个位置来引入漏洞。

图3. 对于图1a中的代码生成的漏洞,未进行提示工程。

RQ4 提示工程的必要性

提示的质量显著影响模型的响应质量;提供的上下文越多,模型产生的响应就越好。在我们问题的背景下,识别最不关注语句(Least Attended Statements,LASs)的位置带来三个好处:(1)生成具有类似表示的漏洞,与原始代码相比(难以检测的漏洞),(2)强制模型更改多行代码(难以修复的漏洞),以及(3)减少搜索空间,即可以注入漏洞的位置。这将帮助模型专注于代码的最重要部分,并生成更少但更有效的漏洞。我们之前的研究问题证实了提示工程的能力,可以生成复杂的漏洞。在没有提示工程的情况下生成这些漏洞将需要更多时间并且成本更高。例如,考虑提示一个LLM为图1a中的代码生成一个漏洞,实现通过13行代码的逻辑(一些行已分割以便更好地呈现)。在这个方法中有两个最不关注的语句(LASs),用绿色突出显示。

图3中的代码片段显示了通过提示GPT-3.5-turbo六次生成的不同漏洞(漏洞行用红色突出显示)。我们使用了一个简单的,非专门制作的提示,要求它从给定方法生成一个可编译的漏洞。我们可以看到LLM在代码中注入了不同的漏洞(语句删除、更改类型和不正确的方法调用)。但是,没有任何响应更改任何最不关注的语句,因此与BugFarm的漏洞没有重叠。一般来说,对于具有n个语句的给定方法,引入漏洞的更改可以应用于任何行。BugFarm仅选择要更改的语句的k百分比,并指示LLM对它们进行修改,从而大大减少了搜索空间。使用阈值值k = 20%,我们可以将搜索空间减少80%。如果不进行注意力分析,减少搜索空间的朴素方法将随机选择k个百分比的语句。如果不是最不关注的语句之一,它们可以很容易地被学习型技术检测或修复,就像前面的研究问题所示。

总结。提示工程有助于BugFarm生成难以检测和难以修复的漏洞。在没有提示工程的情况下生成类似数据集的机会非常狭窄,如果不是不可能的话,这是因为中等到长的方法具有相对较大的搜索空间。

RQ5 总体表现

图4. BugFarm相对于替代方法在未确认漏洞生成方面的性能

为了评估BugFarm的性能特征,我们测量了从模型中提取注意力权重所需的时间以及提示LLM(GPT-3.5-turbo)所需的时间。我们还比较了BugFarm与替代方法在漏洞生成的总时间。所有实验都在配有NVIDIA GeForce RTX 3090 GPU(24GB GDDR6X内存)和24个3.50GHz Intel 10920X CPU(128GB内存)的工作站上执行。图4显示了结果,红色虚线表示平均值。从图4中的Attention Analyzer部分可以看出,BugFarm从CodeBERT、CodeT5和NatGen模型中提取和分析注意力权重的平均时间分别为68、69和86毫秒。对每个方法进行提示的平均时间也约为9秒(中间的提示框图表)。提示时间可能受多种因素影响,包括模型上的流量和提示大小,即提示中的标记数量。 我们还测量了每种技术生成未确认漏洞所需的总时间(图4中的End-to-End Unconfirmed Bug Generation)。与注意力分析和提示相比,BugFarm的其他子组件的开销,如解析和漏洞选择,可以忽略不计。因此,每种方法生成所有BugFarm未确认漏洞的平均时间为9.29秒(主要受提示时间的支配)。相比之下,LEAM和BERT每种方法生成未确认漏洞的平均时间分别为35和28秒。这是因为这些方法生成了更多未确认的漏洞,如表1中的#UB列所示。对于LEAM来说,这个时间不包括模型的训练时间,该时间为24小时。此外,由于BERT花费了很长时间来突变大型类,我们对其设置了15分钟的超时,以避免生成时间过长。验证未确认漏洞也非常耗时;我们花费了大约80000个CPU核小时来验证来自BERT、LEAM和BugFarm的250万多个突变体。

总结。与替代方法相比,BugFarm是一种高效且可扩展的漏洞生成技术。更准确地说,BugFarm在端到端未确认漏洞生成方面比LEAM和BERT分别快74%和67%。

转述:葛一飞

0 阅读:0

互联不一般哥

简介:感谢大家的关注