运用DeepState对API进行含糊测验(下)

本文,我将对测验的成果进行评价,看看DeepState测验是否与John的含糊测验相同有用?看看这两种办法在查找某些潜在的缝隙方面是否相同有用?符号履行是否也有相同的作用呢? 变异测验 变异测验(M...

本文,我将对测验的成果进行评价,看看DeepState测验是否与John的含糊测验相同有用?看看这两种办法在查找某些潜在的缝隙方面是否相同有用?符号履行是否也有相同的作用呢?

变异测验

变异测验(Mutation Testing)(有时也叫做“变异剖析”)是一种在细节方面改善程序源代码的软件测验办法。这些所谓的变异,是根据杰出界说的变异操作,这些操作或许是模仿典型运用过错(例如:运用过错的操作符或许变量姓名),或许是强制发生有用地测验(例如使得每个表达式都等于0)。意图是协助测验者发现有用的测验,或许定位测验数据的缺点,或许是在履行中很少(或从不)运用的代码的缺点。

在上一篇文章中,我现已手动引入了一个缝隙,便是便利进行变异测验。现在有许多可用于变异测验的东西,其间大部分是用Java编写的。一般来说,用C代码编写的东西都不太安稳,或很不好用。为此,我和其他搭档还专门编写了一个东西,即universalmutator,这是一个朴实根据正则表达式指定的代码行重写来生成变异的东西,答应多种言语的变异,包括C和C ++以及Swift,Solidity,Rust等许多曾经没有变异测验东西的其他言语。我将在本文中运用universalmutator来查看含糊器在检测人工红黑树缝隙方面的体现。除了惯例检测之外,universalmutator的一个长处是它能够发生许多新的变异目标,包括那些常常同等但有时会发生奇妙的行为差异的变异目标。也便是说,这些奇妙的变异目标很或许便是某个难以被检测到的缝隙。别的,现在大多数变异体系都不支撑这些变异目标。

装置universalmutator并生成一些变异目标很简单:

pip install universalmutator
mkdir mutants
mutate red_black_tree.c --mutantDir mutants
这将发生很多的变异目标,其间大多数不会编译(universalmutator不会解析C代码,所以毫不古怪它的许多变异目标都不是有用的C),我能够经过对变异目标运转“变异剖析”来解析变异目标。

analyze_mutants red_black_tree.c "make clean; make" --mutantDir mutants
这将生成两个文件:killed.txt,包括没有经过编译的变异目标,以及notkilled.txt,包括实践编译的1120个变异目标。为了查看变异某个目标是否被禁用,剖析东西仅仅确认引号中的指令是回来非零退出代码仍是超时即可。默许超时为30秒,除非你的设备运转速度很慢,不然30秒最够用了。

假如我将包括有用(编译)变异目标的notkilled.txt文件复制到另一个文件,我就能够进行一些真实的变异测验:

cp notkilled.txt compile.txt
analyze_mutants red_black_tree.c "make clean; make fuzz_rb; ./fuzz_rb" --mutantDir mutants --verbose --timeout 120--fromFile compile.txt
输出内容如下所示:

ANALYZING red_black_tree.c
COMMAND: ** ['make clean; make fuzz_rb; ./fuzz_rb'] **
#1: [0.0s 0.0% DONE]
  mutants/red_black_tree.mutant.2132.c NOT KILLED
  RUNNING SCORE: 0.0
...
Assertion failed: (left_black_cnt == right_black_cnt), function checkRepHelper, file red_black_tree.c, line 702.
/bin/sh: line 1: 30015 Abort trap: 6           ./fuzz_rb
#2: [62.23s 0.09% DONE]
  mutants/red_black_tree.mutant.1628.c KILLED IN 1.78541398048
  RUNNING SCORE: 0.5
  ...
类似的指令将在DeepState 含糊器和libFuzzer上运转变异测验。只需把 make fuzz_rb; ./fuzz_rb改变为make ds_rb; ./ds_rb –fuzz –timeout 60 –exit_on_fail,然后将其内置到DeepState 含糊器。关于libFuzzer,由于libFuzzer的冗长输出会搅扰实践的变异成果的输出,为了加速测验速度,我要将环境变量LIBFUZZER_EXIT_ON_FAIL设置为TRUE,并将输出管道设置为/dev/null。

export LIBFUZZER_EXIT_ON_FAIL=TRUE
analyze_mutants red_black_tree.c "make clean; make ds_rb_lf; ./ds_rb_lf -use_value_profile=1 -detect_leaks=0 -max_total_time=60 >& /dev/null" --mutantDir mutants --verbose --timeout 120 --fromFile compile.txt
该东西会生成2602个变异目标,但实践编译的只要1120个。经过60秒的测验预算来剖析这些变异目标,我能够更好的了解含糊测验的质量。DeepState的BF(Brute-Force)算法含糊器禁用了其间的797个变异目标(71.16%),而John的原始含糊器则禁用了822(73.39%)个变异目标。接着,再花60秒含糊那些没有被这些含糊器禁用的变异体,我发现它们仍是不会被禁用。libFuzzer的功能居然和DeepState惊人地类似,60秒内禁用797个变异体。这说明,变异目标是相同的。

可见,DeepState的含糊器在前期的含糊作用不如John的含糊器。这并不古怪,由于在含糊测验中,速度是王道。由于DeepState正在解析字节省,为了保存溃散而分叉,并生成很多的、用户操控的日志记载,因而它不或许像John的含糊器相同快速的生成和履行测验。

而libFuzzer的速度乃至更慢,除了DeepState含糊器供给的一切服务((除了溃散分岔,溃散分岔由libFuzzer自己处理)之外,libFuzzer还确认代码覆盖率,并为每个测验核算值概要文件,并履行根据这些输入质量评价的未来测验所需的核算。

这便是John的含糊器禁用25个变异目标的原因,那DeepState就彻底不禁用这些变异目标吗?不彻底是。假如我查看别的25个变异目标,就会发现每个变异目标都涉及到将指针上的等式比较变成不等式。例如:

<   if ( (y == tree->root) ||
---
>   if ( (y <= tree->root) ||
DeepState含糊器没有找到这些变异目标,由于它在fork中运转每个测验。别的,由于大多数分配都在fork中,代码没有分配满足的时刻来运用满足的地址空间来对这些特定的查看进行测验。从理论上讲,libFuzzer不应该呈现这种状况,它运转时没有分叉。当然,假如咱们给缓慢而安稳的libFuzzer 5分钟而不是60秒,它也会捕捉到一切这些变异目标。再多的含糊处理也不能协助DeepState含糊器,在这种状况下,这个缝隙就显得十分古怪,并且不太简单被疏忽。问题不在于含糊器的速度,也不在于测验的质量,而是不同的含糊测验环境在我实践运转的测验中发生细微差别。

[1] [2] [3]  黑客接单网

  • 发表于 2024-09-22 08:12
  • 阅读 ( 271 )
  • 分类:互联网

0 条评论

请先 登录 后评论
fang129
fang129

698 篇文章

你可能感兴趣的文章

相关问题