afl-cov计算代码覆盖率

GitHub - mrash/afl-cov: Produce code coverage results with gcov from afl-fuzz test cases

这里需要用到的工具之一是GCOV ,它随gcc一起发布,所以不需要再单独安装,和afl-gcc插桩编译的原理一样,gcc编译时生成插桩的程序,用于在执行时生成代码覆盖率信息。

另外一个工具是LCOV,它是GCOV的图形前端,可以收集多个源文件的gcov数据,并创建包含使用覆盖率信息注释的源代码HTML页面。

最后一个工具是afl-cov,可以快速帮助我们调用前面两个工具处理来自afl-fuzz测试用例的代码覆盖率结果。

afl-cov可以解析已经执行完毕的afl-fuzz输出结果,也可以与afl-fuzz同时运行,实时监控每次测试的覆盖率。

安装afl-cov:

bash 复制代码
1、apt-get install afl-cov # 但这个版本似乎不支持分支覆盖率统计

2、从Github下载最新版本,下载完无需安装直接运行目录中的Python脚本即可使用
$ apt-get install lcov
$ git clone https://github.com/mrash/afl-cov.git
$ ./afl-cov/afl-cov -V

还是以Fuzz test.c为例,计算Fuzzing过程的代码覆盖率流程如下:

cpp 复制代码
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <signal.h> 

int AFLTest(char *str)
{
    int len = strlen(str);
    if(str[0] == 'A' && len == 6)
    {
        raise(SIGSEGV);
        //濡傛灉杈撳叆鐨勫瓧绗︿覆鐨勯瀛楃涓篈骞朵笖闀垮害涓?锛屽垯寮傚父閫€鍑?    }
    else if(str[0] == 'F' && len == 16)
    {
        raise(SIGSEGV);
        //濡傛灉杈撳叆鐨勫瓧绗︿覆鐨勯瀛楃涓篎骞朵笖闀垮害涓?6锛屽垯寮傚父閫€鍑?    }
    else if(str[0] == 'L' && len == 66)
    {
        raise(SIGSEGV);
        //濡傛灉杈撳叆鐨勫瓧绗︿覆鐨勯瀛楃涓篎骞朵笖闀垮害涓?6锛屽垯寮傚父閫€鍑?    }
    else
    {
        printf("it is good!\n");
    }
    return 0;
}

int main(int argc, char *argv[])
{
    char buf[100]={0};
    gets(buf);   //瀛樺湪鏍堟孩鍑烘紡娲?    printf(buf); //瀛樺湪鏍煎紡鍖栧瓧绗︿覆婕忔礊
    AFLTest(buf);
    
    return 0;
}

1、使用gcov重新编译源码 ,在CFLAGS中添加"-fprofile-arcs"和"-ftest-coverage"选项,可以在--prefix中重新指定一个新的目录以免覆盖之前alf插桩的二进制文件。

$ afl-gcc -fprofile-arcs -ftest-coverage -g -o test_cov test.c

  • -ftest-coverage:在编译的时候产生与源代码同名的.gcno文件,它包含了重建基本块图和相应的块的源码的行号的信息。

  • -fprofile-arcs:在运行编译过的程序的时候,会产生.gcda文件,它包含了弧跳变的次数等信息。

编译成功后,除了会出现test_cov之外,还会有一个与源码test.c同名的.gcno文件:

2、使用afl-fuzz测试

$ afl-fuzz -i good-seeds/ -o test-cov/ -- ./test_cov

生成的文件:

3、执行afl-cov分析覆盖率

$ afl-cov -d test-cov/ --coverage-cmd "cat AFL_FILE | ./test_cov" -c . --enable-branch-coverage --overwrit

  • -d AFL_FUZZING_DIR, --afl-fuzzing-dir AFL_FUZZING_DIR:指定afl-fuzz输出目录;

  • --live用于处理一个还在实时更新的AFL目录,当afl-fuzz停止时,afl-cov将退出;

  • --enable-branch-coverage:用于开启边缘覆盖率(分支覆盖率)统计;

  • -c CODE_DIR, --code-dir CODE_DIR:用于指定源码目录;

  • -e COVERAGE_CMD, --coverage-cmd COVERAGE_CMD:用来设置要执行的程序和参数,其中的AFL_FILE和afl中的"@@"类似,afl-cov会自动将AFL_FILE替换为fuzzer输出结果的文件名(也就是id:0000开头的文件),LD_LIBRARY_PATH则用来指定程序的库文件。

成功执行的结成功执行的结果如下所示:

这里是解析已经执行完毕的afl-fuzz输出结果,但我们可以使用--live参数与afl-fuzz同时运行,实时监控每次测试的覆盖率。

$ afl-cov -d test-cov/ --live --coverage-cmd "cat AFL_FILE | ./test_cov" -c . --enable-branch-coverage --overwrit

在afl-fuzz测试终止后,afl-cov会随之自动停止,并给出一系列分析结果:

两种方式都会在afl-fuzz结果输出目录生成cov目录:

分析结果保存在afl-fuzz测试结果目录下的cov/文件夹中。:

  • zero-cov中保存了在运行过程中从未被执行到的代码或是函数;

  • pos-cov中保存了在运行过程中被执行过至少一次的内容。

  • 在cov/目录下的web文件夹中有一个index.html文件,即根据分析结果给出的可视化页面。

打开cov/web/index.html页面,它既提供了概述页面,显示各个目录的覆盖率:

也可以在点击进入某个目录查看某个具体文件的覆盖率:

点击进入每个文件,还有更详细的数据。每行代码前的数字代表这行代码被执行的次数,没有执行过的代码会被红色标注出来:

相关推荐
看山还是山,看水还是。10 天前
软件工程 设计的复杂性
笔记·流程图·软件工程·团队开发·代码规范·内容运营·代码覆盖率
敲代码敲到头发茂密2 个月前
Java面向对象编程进阶(一)
java·开发语言·数据结构·算法·代码覆盖率·1024程序员节
IT_xiao小巫3 个月前
【可测试性实践】C++ 单元测试&代码覆盖率统计入门
c++·单元测试·代码覆盖率
General_G6 个月前
CI构建pipelines
ci/cd·单元测试·软件构建·代码覆盖率
龙智DevSecOps解决方案6 个月前
展会邀请 | 龙智即将亮相2024上海国际嵌入式展,带来安全合规、单一可信数据源、可追溯、高效协同的嵌入式开发解决方案
单元测试·需求分析·测试覆盖率·代码覆盖率
骑着蜗牛追汽车7 个月前
如何使用golang自带工具对代码进行覆盖率测试
golang·代码覆盖率
龙测科技10 个月前
低代码测试自动化
运维·功能测试·低代码·自动化·代码覆盖率
龙测科技10 个月前
12种移动测试类型及示例
功能测试·测试·代码覆盖率
奇妙之二进制10 个月前
编译链接实战(22)C/C++代码覆盖率统计报告生成
c语言·c++·代码覆盖率
慕城南风1 年前
Python之代码覆盖率框架coverage使用介绍
python·代码覆盖率