实验三:klee的执行重现机制(示例分析)

结论性内容:

(1)如果是在程序中使用klee_make_symbolic,则可以使用下列脚本进行重现。

export LD_LIBRARY_PATH=/home/klee/xiaojiework/klee-xiaojie/build/debug/lib/:$LD_LIBRARY_PATH
gcc -L /home/klee/xiaojiework/klee-xiaojie/build/debug/lib/ test4.c -lkleeRuntest
KTEST_FILE=klee-last/test000015.ktest ./a.out

(2)如果是对命令行参数进行建模,即对klee进行符号执行的时候,使用 --posix-runtime选项,设定sym-args等参数,则重现只能用klee-replay,不能用(1)中的脚本。不需要链接到klee的运行库-lkleeRuntest,并且直接用gcc对代码进行编译成本地代码即可。

示例代码:

#include <stdio.h>//test.c
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <klee/klee.h>
int main(int argc, char* argv[]) {
    int result = argc > 1 ? atoi(argv[1]) : 0;
    if (result == 42)
    {
    klee_assert(0);
    }
    return result;
}

脚本:

clang -I /home/klee/xiaojiework/klee/include/ -emit-llvm -c -g test2.c
klee --libc=uclibc --posix-runtime test2.bc --sym-args 0 1 3

执行结果:

[email protected]:~/kleeexperiment/modeltest$ klee --libc=uclibc --posix-runtime test2.bc --sym-args 0 1 3

KLEE: NOTE: Using klee-uclibc : /usr/local/lib/x86_64-linux-gnu/klee/runtime/klee-uclibc.bca

KLEE: NOTE: Using model: /usr/local/lib/x86_64-linux-gnu/klee/runtime/libkleeRuntimePOSIX.bca

KLEE: output directory is "/home/klee/kleeexperiment/modeltest/klee-out-31"

KLEE: Using STP solver backend

KLEE: WARNING ONCE: calling external: syscall(16, 0, 21505, 71386000)

KLEE: WARNING ONCE: calling __user_main with extra arguments.

KLEE: WARNING ONCE: Alignment of memory from call "malloc" is not modelled. Using alignment of 8.

KLEE: ERROR: /home/klee/kleeexperiment/modeltest/test2.c:22: ASSERTION FAIL: 0

KLEE: NOTE: now ignoring this error at this location

KLEE: done: total instructions = 11567

KLEE: done: completed paths = 73

KLEE: done: generated tests = 69

查看对应assertion错误的测试用例:

我们直接对程序输入+42,进行执行重现。

可以看到,即使是gcc test2.c -o test2(不是gcc -L /home/klee/xiaojiework/klee-xiaojie/build/debug/lib/ test2.c -lkleeRuntest),并且LD_LIBRARY_PATH是空的。为什么gcc能够在不链接到-lkleeRuntest的时候,对klee-assert进行解释呢?

这是因为在klee/klee.h中是这样定义的:

# define klee_assert(expr) \

((expr) \

? (void) (0) \

: __assert_fail (#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__)) \

所以压根不需要链接到kleeRuntest运行库。

下面改用--sym-arg选项,

clang -I /home/klee/xiaojiework/klee/include/ -emit-llvm -c -g test2.c
klee --libc=uclibc --posix-runtime test2.bc --sym-arg 3

可以看到,和使用--sym-args生成了同样的测试用例。即+42,我们可以直接在命令行使用./test2 +42进行执行重现。

但是,在实际的实验进程中(由于反复试验,求解每次随机返回一个解),我还生成了另外内容的测试用例,同样覆盖assertion错误。内容如下:

对于这个测试用例,内容是\x0b42,实际上就是三个字符,第一个是垂直制表符号,第二个是字符‘4‘,第三个是字符‘2‘。第一个无法直接通过命令行输入,所以我们使用klee的重现机制。

我们同时搜集的还有内容是‘42\x00\x00’的测试用例,连同之前的两个测试用例,三个测试用例都放在了generatedtests目录下:

使用脚本:

均没有任何assertion fail的反应。但是使用klee-repaly的时候,

三个测试输入依次是:

垂直字表符,42(垂直字表符,我们从键盘是敲不出来的)

42

+42

所以,对命令行建模的时候,需要用klee-replay的机制。

我们采取在程序中使用klee_make_symbolic的方式,再分析一下klee执行重现机制。

代码:

int main() { //test4.c
    int argc=2;
    int size=4;
    char argv[size];
    klee_make_symbolic(argv, sizeof argv, "argv");
    argv[3]=‘\0‘;
    int result = argc > 1 ? atoi(argv) : 0;
    if (result == 42)
    {
    klee_assert(0);
   //printf("yes");
    }
    return result;
}

由于不需要对命令行参数进行建模,我们使用如下脚本:

clang -I /home/klee/xiaojiework/klee/include/ -emit-llvm -c -g test4.c

klee --optimize --libc=uclibc test4.bc --sym-args 0 1 3

去除了--posix-runtime选项,因为不需要对命令行参数进行建模。需要保留--libc=uclibc选项,因为还要对atoi函数进行建模和处理。

下一步使用klee的重现机制。我们看到,可以使用KTEST_FILE的方式。

再试试klee-replay,结果显示:

由于test4.c中有klee_make_symbolic的语句,导致我们必须链接到lkleeRuntest才能执行重现。我们手动去掉这个语句,再编译成本地可执行代码,不链接到kleeRuntest运行库,即直接使用gcc -o test4 test4.c。结果仍然报错。

分析完毕!klee-replay和KTestFile指定文件各有应用场景,正如随笔一开始所给出的结论性内容。

时间: 2024-10-10 01:53:17

实验三:klee的执行重现机制(示例分析)的相关文章

Android AsyncTask内部线程池异步执行任务机制简要分析

如下分析针对的API 25的AsyncTask的源码: 使用AsyncTask如果是调用execute方法则是同步执行任务,想要异步执行任务可以直接调用executeOnExecutor方法,多数情况下我们会使用AsyncTask内部静态的线程池, THREAD_POOL_EXECUTOR,这里并不是要分析AsyncTask内部的流程,而是简单介绍下线程池的工作流程.可以看到THREAD_POOL_EXECUTOR的配置如下: new ThreadPoolExecutor( CORE_POOL_

20145326蔡馨熠 实验三 &quot;敏捷开发与XP实践&quot;

20145326蔡馨熠 实验三 "敏捷开发与XP实践" 程序设计过程 实验内容 使用 git 上传代码 使用 git 相互更改代码 实现代码的重载 一.git上传代码 首先我通过git上传一个名为“shiyansan”的代码. 设置权限: 然后我的partner从网上把这个文档下载到他的电脑中. 然后再修改,再上传: 我的partner:-  [20145211黄志远开源托管代码](https://git.oschina.net/nostalgia_) 二.敏捷开发与XP 软件工程是把

20135130实验三报告

实验三报告 北京电子科技学院(BESTI) 实     验    报     告 课程:Java 班级: 1351    姓名:王川东  学号:20135130 成绩:              指导教师:娄嘉鹏    实验日期:2015.5.8 实验密级:          预习程度:          实验时间:15:30~18:00 仪器组次:20         必修/选修:选修      实验序号:02 实验名称:敏捷开发与XP实践 实验仪器: 名称 型号 数量 计算机 lenovo

20135337朱荟潼——实验三

实验三 敏捷开发与XP实践 实验内容 1. XP基础 2. XP核心实践 3. 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程.软件工程包括下列领域:软件需求分析.软件设计.软件构建.软件测试和软件维护. 人们在开发.运营.维护软件的过程中有很多技术.做法.习惯和思想体系.软件工程把这些相关的技术和过程统一到一个体系中,叫“软件开发流程”.软件开发流程的目的是为了提高软件开发.运营.维护的效率,并提高软件的质量.用户满意度.

20135331文艺实验三

实验三 敏捷开发与XP实践 实验内容 1. XP基础 2. XP核心实践 3. 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程.软件工程包括下列领域:软件需求分析.软件设计.软件构建.软件测试和软件维护. 人们在开发.运营.维护软件的过程中有很多技术.做法.习惯和思想体系.软件工程把这些相关的技术和过程统一到一个体系中,叫“软件开发流程”.软件开发流程的目的是为了提高软件开发.运营.维护的效率,并提高软件的质量.用户满意度.

2017-2018-1 20155229 实验三 实时系统

2017-2018-1 20155229 实验三 实时系统 实验目的 了解实时系统的信息.特点等内容. 学习客户端和服务器之间的工作原理,并编写代码实现. 实验步骤 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服务器 服务器返加文本文件中的单词数 wc命令的功能: 统计指定文件中的字节数.字数.行数,并将统计结果显示输出.该命令统计指定文件中的字节数.字数.行数.如果没有

2017-2018-1 20155208 20155212 实验三 实时系统

2017-2018-1 20155212 实验三 实时系统 1 学习使用Linux命令wc(1) 题目 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服务器 服务器返加文本文件中的单词数 步骤 使用man wc命令查看wc wc命令详解 语法:wc [选项] 文件 选项含义 c:统计字节数 l:统计行数 w:统计字数 使用示例 实现难点: 如何统计单词数? 使用od -tc命令查看文本中单词之间如何间隔 单词间通过' '.'\r

2017-2018-1 20155305实验三 实时系统

2017-2018-1 20155305实验三 实时系统 任务一 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服务器 服务器返加文本文件中的单词数 上方提交代码 附件提交测试截图,至少要测试附件中的两个文件 使用man wc命令查看wc命令的基本用法: 可知wc命令的功能为:统计指定文件中的字节数.字数.行数等,并将统计结果显示输出.常用的参数为: -c:统计字节数 -l:统计行数 -m:统计

2017-2018-1 20155227 实验三 实时系统

2017-2018-1 20155227 实验三 实时系统 实验目的,实验步骤 实验过程如下. 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服务器 服务器返加文本文件中的单词数 上方提交代码 附件提交测试截图,至少要测试附件中的两个文件 client.c: #include<netinet/in.h> // sockaddr_in #include<sys/typ