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