1 个不稳定版本
| 0.6.0 | 2023年2月4日 | 
|---|---|
| 0.1.0 |  | 
#686 in WebAssembly
220KB
 5.5K  SLoC
wasmut
wasmut 是一个针对WebAssembly WASI 模块的突变测试工具。
目录
安装
目前,wasmut 正式支持Linux和Windows。macOS也应大部分工作,但我无法保证任何事情,因为我没有访问Mac。
预构建的二进制文件
对于Linux和Windows,可以在本仓库的发布页面找到针对 amd64 架构的预构建二进制文件。
使用Cargo安装
wasmut是用Rust实现的,因此您需要Rust工具链来编译该项目。最低支持的Rust版本(MSRV)是1.67。
要从crates.io安装最新的wasmut版本,请运行以下命令
> cargo install wasmut 
这将默认将 wasmut 安装到 $HOME/.cargo/bin。请确保此路径包含在我们的 $PATH 变量中。
开发
如果您想修改 wasmut,只需检出仓库。请确保包含 testdata 子模块。
> git clone --recursive https://github.com/lwagner94/wasmut
一旦克隆了仓库,您可以使用 test 命令运行测试套件。
cargo test
您可能希望以发布构建运行 wasmut。在开发构建中,运行突变需要更多时间。
cargo run --release -- mutate testdata/simple_go/test.wasm -C
您可以使用 coverage.sh 脚本来生成测试覆盖率报告。请确保已安装 grcov 和Rust编译器的夜间版本。
./coverage.sh
快速入门
安装后,您可以使用 wasmut。首先,您可以尝试 testdata 文件夹中的示例。如果您想用自己的模块使用 wasmut,请确保查看 WebAssembly模块要求 章节。
如果您不带任何标志运行 mutate 命令,wasmut 将尝试在当前目录中加载一个名为 wasmut.toml 的文件,如果找不到它,将回退到默认选项。
> # Run wasmut using default options (no filtering, all operators)
> wasmut mutate testdata/simple_add/test.wasm
[INFO ] No configuration file found or specified, using default config
[INFO ] Using 8 workers
[INFO ] Generated 37 mutations
...
使用 -C/-c 标志,您可以指示 wasmut 从不同的路径加载配置文件。-C 标志将尝试从与模块相同的目录加载 wasmut.toml,而 - 允许您提供配置文件的完整路径。
> wasmut mutate testdata/simple_add/test.wasm -C
[INFO ] Loading configuration file from module directory: "testdata/simple_add/wasmut.toml"
[INFO ] Using 8 workers
[INFO ] Generated 1 mutations
[INFO ] Original module executed in 40 cycles
[INFO ] Setting timeout to 80 cycles
/home/lukas/Repos/wasmut/testdata/simple_add/simple_add.c:3:14: 
KILLED: binop_add_to_sub: Replaced I32Add with I32Sub
    return a + b;
              ^
ALIVE           0
TIMEOUT         0
ERROR           0
KILLED          1
Mutation score  100%
默认情况下,wasmut 将将结果打印到控制台 - 如上所示。如果您添加 --report html 选项,wasmut 将在 wasmut-report 文件夹中创建一个 HTML 报告。
> wasmut mutate testdata/simple_go/test.wasm -C --report html
[INFO ] Loading configuration file from module directory: "testdata/simple_go/wasmut.toml"
[INFO ] Using 8 workers
...
 

命令行界面
帮助
显示帮助菜单
list-files
List all files of the binary.
If a config is provided, this command will also show whether the file is allowed to be mutated. By
default, wasmut will try to load a wasmut.toml file from the current directory
USAGE:
    wasmut list-files [OPTIONS] <WASMFILE>
ARGS:
    <WASMFILE>
            Path to the wasm module
OPTIONS:
    -c, --config <CONFIG>
            Load wasmut.toml configuration file from the provided path
    -C, --config-samedir
            Attempt to load wasmut.toml from the same directory as the wasm module
    -h, --help
            Print help information
    -V, --version
            Print version information
list-functions
List all functions of the binary.
If a config is provided, this command will also show whether the function is allowed to be mutated.
By default, wasmut will try to load a wasmut.toml file from the current directory
USAGE:
    wasmut list-functions [OPTIONS] <WASMFILE>
ARGS:
    <WASMFILE>
            Path to the wasm module
OPTIONS:
    -c, --config <CONFIG>
            Load wasmut.toml configuration file from the provided path
    -C, --config-samedir
            Attempt to load wasmut.toml from the same directory as the wasm module
    -h, --help
            Print help information
    -V, --version
            Print version information
list-operators
List all available mutation operators.
If a config is provided, this command will also show whether the operator is enabled or not. By
default, wasmut will try to load a wasmut.toml file from the current directory
USAGE:
    wasmut list-operators [OPTIONS] [WASMFILE]
ARGS:
    <WASMFILE>
            Path to the wasm module
OPTIONS:
    -c, --config <CONFIG>
            Load wasmut.toml configuration file from the provided path
    -C, --config-samedir
            Attempt to load wasmut.toml from the same directory as the wasm module
    -h, --help
            Print help information
    -V, --version
            Print version information
mutate
Generate and run mutants.
Given a (possibly default) configuration, wasmut will attempt to discover mutants and subsequently
execute them. After that, a report will be generated
USAGE:
    wasmut mutate [OPTIONS] <WASMFILE>
ARGS:
    <WASMFILE>
            Path to the wasm module
OPTIONS:
    -c, --config <CONFIG>
            Load wasmut.toml configuration file from the provided path
    -C, --config-samedir
            Attempt to load wasmut.toml from the same directory as the wasm module
    -h, --help
            Print help information
    -o, --output <OUTPUT>
            Output directory for reports
            
            [default: wasmut-report]
    -r, --report <REPORT>
            Report output format
            
            [default: console]
            [possible values: console, html]
    -t, --threads <THREADS>
            Number of threads to use when executing mutants
    -V, --version
            Print version information
new-config
Create new configuration file
USAGE:
    wasmut new-config [PATH]
ARGS:
    <PATH>    Path to the new configuration file
OPTIONS:
    -h, --help       Print help information
    -V, --version    Print version information
run
Run module without any mutations
USAGE:
    wasmut run [OPTIONS] <WASMFILE>
ARGS:
    <WASMFILE>    Path to the wasm module
OPTIONS:
    -c, --config <CONFIG>    Load wasmut.toml configuration file from the provided path
    -C, --config-samedir     Attempt to load wasmut.toml from the same directory as the wasm module
    -h, --help               Print help information
    -V, --version            Print version information
WebAssembly模块要求
wasmut 目前支持使用 WebAssembly系统接口(WASI) 的WebAssembly模块。 wasmut 将以 _start 函数作为模块的入口点执行,并将模块的退出代码(由 main 的返回值或显式调用 exit 设置)用于确定模块测试的结果 - 0 表示成功,任何非零退出代码表示失败。
wasmut 在突变过滤和报告生成方面大量使用 DWARF 调试信息。请确保使用正确的编译器标志编译 WebAssembly 模块,以确保调试信息嵌入到模块中。
此外,编译器优化对 wasmut 的性能有很强的影响。需要做更多实验才能给出建议,但到目前为止,请参考 testdata 目录中的示例,了解应使用哪些编译器选项。
配置选项
[engine] 部分
- 
timeout_multiplier:在执行突变之前,wasmut 将在没有突变的情况下运行 wasm 模块,并测量执行所需的时间周期数。突变允许以timeout = original_cycles * timeout_multiplier的超时时间执行。timeout_multiplier = 2.0
- 
map_dirs:将目录映射到 WebAssembly 运行时。默认情况下,模块无法访问宿主机的文件系统。如果您的模块需要访问任何文件,您可以使用map_dirs选项来定义路径映射。# Map testdata/count_words/files to /files map_dirs = [["testdata/count_words/files", "files"],]
- 
coverage_based_execution:在执行突变之前,wasmut 将在没有突变的情况下运行 wasm 模块,并生成覆盖率信息。如果启用了coverage_based_execution,则将跳过突变执行中从未执行过的突变指令。默认为true。coverage_based_execution = true
- 
meta_mutant:如果启用了meta_mutant,将生成包含所有突变的单个突变。在执行过程中,通过设置标志来激活突变。这种方法的优点是只需要编译单个突变,因此执行时间显著减少。默认为true。meta_mutant = true
[filter] 部分
- 
allowed_function/allowed_file:默认情况下,所有文件和函数都允许,这意味着每个WebAssembly指令都可能被修改。这并不太实用,因此可以指定允许列表来指定函数和/或文件。在allowed_functions和allowed_files中,您可以指定用于匹配函数和文件名的正则表达式列表。如果wasm-instruction的函数或文件至少匹配一个对应的正则表达式,则允许修改该指令。空的正则表达式也匹配所有内容。使用wasmut list-files或wasmut list-functions命令获取wasm模块中所有函数和文件的列表。allowed_functions = ["^add"] allowed_files = ["src/add.c", "src/main.c"]
[operators]部分
- 
enabled_operators:默认情况下,所有运算符都允许。如果您不希望如此,可以使用enabled_operators选项来指定应启用哪些运算符。该选项是一个正则表达式列表。使用wasmut list-operators命令或查阅文档以获取所有运算符的列表。# Enable binop_sub_to_add and all relop_* operators enabled_operators = ["binop_sub_to_add", "relop"]
[report]部分
- 
path_rewrite:在生成报告时,wasmut需要访问原始源文件。wasmut使用嵌入在WebAssembly模块中的DWARF调试信息来定位它们。由于DWARF将源文件的绝对路径嵌入到模块中,如果您想为在其他主机上构建的WebAssembly模块生成报告,这可能会出现问题。path_rewrite选项允许指定一个正则表达式和一个替换,该替换将在创建报告之前应用于任何源文件路径。内部使用Rust的Regex::replace。有关任何高级替换场景,请查阅文档。# Replace /home/user/wasmut/ with "build" # e.g. /home/user/test/main.c -> # build/test/main.c path_rewrite = ["^/home/user/", "build"]
完整示例
[engine]
timeout_multiplier = 4.0
map_dirs = [["testdata/count_words/files", "files"],]
coverage_based_execution = true
meta_mutant = true
[filter]
allowed_functions = ["^count_words"]
#allowed_files = [""]
[operators]
enabled_operators = ["binop_sub_to_add", "relop"]
[report]
path_rewrite = ["^.*/wasmut/", ""]
支持的变异运算符
wasmut中可用的变异运算符目前主要基于mull的运算符
| 名称 | 描述 | 
|---|---|
| binop_sub_to_add | 用加法替换减法 | 
| binop_add_to_sub | 用减法替换加法 | 
| binop_mul_to_div | 用有符号/无符号除法替换乘法 | 
| binop_div_to_mul | 用乘法替换有符号/无符号除法 | 
| binop_shl_to_shr | 用有符号/无符号右移替换位左移 | 
| binop_shr_to_shl | 用有符号/无符号左移替换位右移 | 
| binop_rem_to_div | 用同符号的除法替换余数 | 
| binop_div_to_rem | 用同符号的除法替换余数 | 
| binop_and_to_or | 用或替换与 | 
| binop_or_to_and | 用与替换或 | 
| binop_xor_to_or | 用或替换异或 | 
| binop_or_to_xor | 用异或替换或 | 
| binop_rotl_to_rotr | 用位右旋转替换位左旋转 | 
| binop_rotr_to_rotl | 用位左旋转替换位右旋转 | 
| unop_neg_to_nop | 用nop替换一元否定 | 
| relop_eq_to_ne | 用不等式替换相等测试 | 
| relop_ne_to_eq | 用相等测试替换不等式 | 
| relop_le_to_gt | 用同符号的大于替换小于等于 | 
| relop_le_to_lt | 用同符号的小于替换小于等于 | 
| relop_lt_to_ge | 用同符号的大于等于替换小于 | 
| relop_lt_to_le | 用同符号的小于等于替换小于 | 
| relop_ge_to_gt | 将大于等于替换为相同符号位的大于 | 
| relop_ge_to_lt | 将大于替换为相同符号位的小于 | 
| relop_gt_to_ge | 将大于替换为相同符号位的大于等于 | 
| relop_gt_to_le | 将大于替换为相同符号位的小于等于 | 
| const_replace_zero | 将零常量替换为42 | 
| const_replace_nonzero | 将非零常量替换为0 | 
| call_remove_void_call | 删除对无返回值的函数的调用 | 
| call_remove_scalar_call | 删除对返回单个标量且值为42的函数的调用 | 
作者
wasmut 由 Lukas Wagner 开发。
许可证
版权所有 © 2021-2022 Lukas Wagner。
所有代码均受MIT许可协议的许可。更多信息请参阅 LICENSE.txt 文件。
依赖项
~27–41MB
~678K SLoC