Page 191 - 《软件学报》2026年第7期
P. 191

2876                                                       软件学报  2026  年第  37  卷第  7  期


                 保  LLM  能充分理解生成代码的语义. 代码接口部分则提供了所生成代码的外围结构信息, 包括函数名称、参数列
                 表以及依赖库等. 这种提示词组织方式使             LLM  能专注于生成核心逻辑代码, 保证所生成的代码能够被直接编译.
                 生成的程序代码将在后续检测流程中作为待测对象, 进入                   EvalPlus 测试输入生成、符号执行与缺陷检测等阶段,
                 以系统评估其正确性与可靠性.
                  2.2   阶段  2: EvalPlus 测试输入生成
                    在完成了    LLM  代码生成后, 框架进入阶段        2, 该阶段集成了    EvalPlus 中的基于  LLM  以及基于变异的测试输
                 入生成技术, 旨在生成大规模且随机性较高的测试输入, 以保证测试的广度和多样性. 首先, EvalPlus 会利用
                 ChatGPT  根据用户提示词生成种子输入         I seed , 然后使用模糊测试中的变异方法生成大量额外测试输入              I fuzz , 最终产
                 生该阶段的测试输入集, 如公式         (1) 所示:

                                                                                                      (1)
                                                      I EvalPlus = I seed ∪ I fuzz
                  2.3   阶段  3: 基于符号执行的过程

                    ● 为  LLM  生成的程序挂载符号. 阶段       3  与阶段  2  并行运行, 重点通过基于符号执行的技术对关键测试路径进
                 行分析, 并利用约束求解生成高效的边界测试用例, 从而捕获在随机输入下难以触发的深层逻辑性程序缺陷. 与阶
                 段  2  中  EvalPlus 生成的随机性较高、数量庞大的测试输入不同, 阶段           3  生成的测试输入具有更强的针对性与精确
                 性, 能够有效发现仅在特定条件下触发的深层逻辑缺陷. 在阶段                   3, 我们首先为每个     LLM  生成的程序挂载符号, 使
                 程序满足符号执行的要求, 从而可以制导符号执行引擎对程序的关键路径进行精确的约束分析. 符号执行挂载过
                 程主要用于验证并调整由         LLM  生成的程序, 确保其格式符合后续符号执行的要求. 算法                1  展示了该过程的具体步
                 骤. 首先, 系统会判断     LLM  生成的程序    P  是否可编译   (第  2  行). 对于不可编译的程序     (如不完整的函数或无意义
                 的字符串), 将直接忽略      (第  3  行), 不再进行后续处理. 对于可编译的程序, 本文方法会识别其输入参数的数量、类
                 型及名称   (第  7  行). 随后, 根据这些参数, 应用符号挂载模板         (图  4) 对程序  P  进行适配并挂载符号, 从而生成一个
                 新版本程序    P′ (第  9  行), 该程序可被符号执行引擎成功编译与执行          (第  11、12  行).

                 算法  1. 符号执行挂载.
                 输入: LLM  生成的程序    P;
                 输出: 可供符号执行的程序        P′.
                 1.   //步骤  1: 验证程序是否可编译
                 2.   if Compilable(P) = False then
                 3.    Discard(P)
                 4.     return nil
                 5.   end if
                 6.   //步骤  2: 识别输入参数
                 7.   {(p i , t i ) | i ∈  1,...,n } ← ExtractParameters(P)
                 8.   //步骤  3: 挂载符号执行
                 9.   P′ ← Harness(P, {(p i , t i )})
                 10. //步骤  4: 验证程序  P′
                 11. if Compilable(P′) and Executable(P′, KLEE) then
                 12.  return P′
                 13. else
                 14.  return nil
                 15. end if
   186   187   188   189   190   191   192   193   194   195   196