Page 210 - 《软件学报》2026年第3期
P. 210
田朝 等: CoDefense: 面向对抗性攻击的多粒度代码归一化防御方法 1173
阶段和微调阶段. 在预训练阶段, 代码模型在大型未标记语料库上基于自监督的预训练任务来学习通用代码知识,
如通过掩码词元预测 (masked token prediction) [5,24] 来训练代码模型对代码片段中缺失部分的预测能力. 进入微调
阶段后, 经过预训练的代码模型可以在特定的下游任务上进行进一步的微调. 这一步骤使得代码模型能够适应不
同的任务需求, 从而提升其在特定任务上的性能. 通过这种分阶段的学习方式, 预训练代码模型能够在保持通用性
的同时, 实现对特定任务的优化.
一般来说, 预训练代码模型根据模型架构可分为 3 类: Encoder-only 模型 [1,2] 、Decoder-only 模型 [7,25] 和
Encoder-Decoder 模型 [3,6] . Encoder-only 预训练代码模型主要使用双向 Transformer 编码器来学习代码的词元表示.
通过让每个词元相互关注, 增强了模型的代码理解能力. 相比之下, Decoder-only 预训练代码模型通常采用 Left-to-
Right Transformer 架构, 让当前的词元更关注前一个词元, 以更好地捕获词元之间的关联. 被广泛使用的 CodeGPT [7]
是一个代表性的基于 Transformer 的 Decoder-only 预训练代码模型. 此外, 最近的研究 [26,27] 探索了 Encoder-Decoder
[3]
预训练代码模型, PLBART 和 [6] CodeT5 是此类模型的典型代表. 在我们的研究中, 我们采用了最新的对抗性攻击
[6]
[7]
[1]
的实证研究 [16] 中使用的所有 3 个预训练代码模型 (即 CodeBERT 、CodeGPT 和 PLBART ), 分别对应了 3 种
模型架构, 实验模型的具体细节将在第 3.2 节介绍. 通过在相应任务的数据集上对预训练代码模型进行微调, 预训
练代码模型在许多基于代码的任务中取得了突破性的进展, 自动化的代码智能可以协助软件开发并显著提高开发
者的效率 [1−3] .
需要着重指出的是, 当前针对预训练代码模型所设计的对抗性攻击技术 [15,16,19] , 其核心关注点普遍聚焦于以
代码作为直接输入的任务范畴内, 诸如代码分类任务与代码摘要生成等任务. 因此, 这些对抗性攻击技术尚无法直
接迁移至以自然语言为输入的任务 (例如, 代码生成 [28] ). 为了保持与现有对抗性攻击技术的一致性, 本研究的焦点
同样严格限定于处理代码输入的预训练模型范畴, 并遵循既有文献中的术语体系, 继续沿用“预训练代码模型”这
一称谓, 以确保研究的连贯性与学术探讨的精准性.
2.2 对抗性攻击
通过利用上述预训练-微调范式, 预训练代码模型能够从大规模公开代码库中学习和获取领域知识, 这些先验
知识可以进一步用于下游任务, 如漏洞检测 [8] 、代码克隆检测 [9] 和代码摘要生成 [10] . 尽管预训练代码模型在许多
代码相关任务中取得了优异的表现, 但它们依然存在安全风险和鲁棒性问题 [15,16] . 最近的研究表明 [15–17] , 类似于计
算机视觉和自然语言处理领域的深度学习模型, 预训练代码模型在处理两个语义等价的代码片段时可能会产生完
全不同的预测结果. 其中产生错误输出的代码片段 (又称对抗性样本) 是对抗性攻击方法通过对原始代码执行特
定的保留语义的代码转换而生成的. 接下来, 我们分别对基于代码的分类任务和生成任务给出了两个对抗性攻击
的形式化定义.
对于分类任务, 给定一个代码片段 x ∈ X, 将该代码片段 x 处理成预训练代码模型 M : X → Y 所需的格式 (例如
词元序列、抽象语法树、控制流图或数据流图), M 可以预测 x 的概率向量, 其中每个元素代表将 x 归类到相应类
别的概率. 概率最大的类别即为 M 对 x 的最终预测结果. 如果 M 的预测结果 M (x) 与 x 的真实标签 (表示为 y ∈ Y)
不同, 则表示 M 对 x 的预测是错误的; 否则, M 做出了正确的预测.
现有的针对预训练代码模型的对抗性攻击方法通常通过在目标输入执行特定的保留语义的代码转换, 从而生
成对抗性示例 [15,16,18,19] . 为便于理解, 我们将问题定义为: 给定目标代码片段 x, 对抗性攻击方法为目标代码模型 M
找到攻击成功的对抗性样本 x adv . 具体来说, x adv 需要满足 3 个条件 (x adv ≜ x)∧(y = M (x))∧(M (x) , M (x adv )), 下面
给出具体的描述.
(1) x adv ≜ x 表示满足语法约束 (例如 Java 语言的变量名只能包含字母、数字和下划线) 并保留原始代码 x 的
代码语义 (即具有完全相同的功能并在给定任意相同输入的情况下得到相同的输出).
(2) y = M (x) 表示我们只将 M 做出正确预测的测试输入视为目标输入, 这是因为根据现有工作 [15,19] , 对此类输
入的鲁棒性分析更有意义.
(3) M (x) , M (x adv ) 表示 x adv 是从 x 生成的攻击成功的对抗性样本, 成功误导代码模型 M 的预测分类结果.

