fuzz: Add honggfuzz (#206)

* fuzz: Add honggfuzz

- Added honggfuzz in fuzz2/ (alongside libfuzzer in fuzz/)
- Created convenience script for fuzzing binary decoder
- Created a script to convert inputs that cause crashes into arrays so
  that they can be used in unit tests

* Create honggfuzz as subdirectory of fuzz/

- Reorg so that honggfuzz is under fuzz/ instead of in a separate
  sibling-level directory fuzz2
- Update fuzz/README.md to make it explicit that it covers libfuzzer

Note: `cargo fuzz`/libfuzzer seems to insist that its folder exists at
`$REPO/fuzz/` so that's the reason for this particular folder structure.

---------

Co-authored-by: y <y>
This commit is contained in:
greptile
2023-09-04 16:42:34 +00:00
committed by GitHub
parent f72d131d62
commit d9d918b884
10 changed files with 239 additions and 3 deletions

View File

@@ -1,7 +1,10 @@
# DarkFi Fuzzing
This directory contains our fuzz tests. It is a WIP and likley to be
re-organized as we expand the complexity of the tests
This directory contains our fuzz tests. It is a WIP and likely to be
re-organized as we expand the complexity of the tests.
This document covers the usage of `libfuzzer`. An alternative fuzzing
tool `honggfuzz` and its related files are located in `fuzz/honggfuzz`.
## Building the corpora
@@ -73,4 +76,4 @@ This might introduce subtle issues in the fuzzing process especially since
errors found during fuzzing are likely to be precisely the edge-cases that
trigger incompatibilites between build architectures.
Further research is needed here to find a reliable solution.
Further research is needed here to find a reliable solution.

4
fuzz/honggfuzz/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
Cargo.lock
target/
hfuzz_target/
hfuzz_workspace/*/input/*

41
fuzz/honggfuzz/Cargo.toml Normal file
View File

@@ -0,0 +1,41 @@
[package]
name = "darkfi-fuzz2"
version = "0.0.0"
publish = false
edition = "2021"
[package.metadata]
cargo-fuzz = true
[dependencies]
honggfuzz = "0.5"
[dependencies.darkfi]
path = "../.."
features = ["zkas"]
[dependencies.darkfi-serial]
path = "../../src/serial"
features = ["derive", "semver", "collections", "crypto", "hash"]
[patch.crates-io]
blake2b_simd = {git="https://github.com/parazyd/blake2_simd", branch="impl-common"}
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[profile.release]
debug = 1
[[bin]]
name = "zkbinary-decode"
path = "src/zkbinary_decode.rs"
test = false
doc = false
[[bin]]
name = "serial-decode-string"
path = "src/serial_decode_string.rs"
test = false
doc = false

28
fuzz/honggfuzz/README.md Normal file
View File

@@ -0,0 +1,28 @@
# Fuzz2 - honggfuzz
This directory contains files pertaining to fuzz testing with the [`honggfuzz` fuzzer](https://docs.rs/honggfuzz/latest/honggfuzz/).
We're trying this tool out alongside libfuzzer (covered in `darkfi/fuzz/`).
## Comparison to libfuzzer
- Does not halt execution on crashes (can discover multiple crashes in one fuzzing session)
- Fewer memory issues (tool less likely to crash, easier to configure)
- Better UI
## Install
```sh
cargo install honggfuzz
```
## Usage
```sh
# Build targets from Cargo.toml [[bin]] section
cargo hfuzz build
# Run
cargo hfuzz run zkbinary-decode
```
Further info: https://docs.rs/honggfuzz/latest/honggfuzz/#how-to-use-this-crate

View File

@@ -0,0 +1,48 @@
=====================================================================
TIME: 2023-08-30.15:26:53
=====================================================================
FUZZER ARGS:
mutationsPerRun : 5
externalCmd : NULL
fuzzStdin : FALSE
timeout : 5 (sec)
ignoreAddr : (nil)
ASLimit : 0 (MiB)
RSSLimit : 0 (MiB)
DATALimit : 0 (MiB)
wordlistFile : NULL
dynFileMethod :
fuzzTarget : hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string
CRASH:
DESCRIPTION:
ORIG_FNAME: 63ade6888888884b45c5555555557de6.00000010.honggfuzz.cov
FUZZ_FNAME: hfuzz_workspace/serial-decode-string/SIGABRT.PC.7ffff7c8e83c.STACK.c8ecc5e84.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebx.fuzz
PID: 237583
SIGNAL: SIGABRT (6)
PC: 0x7ffff7c8e83c
FAULT ADDRESS: 0x0
INSTRUCTION: mov____%eax,%ebx
STACK HASH: 0000000c8ecc5e84
STACK:
<0x00007ffff7c3e668> [func:UNKNOWN file: line:0 module:/usr/lib/libc.so.6]
<0x00007ffff7c264b8> [func:UNKNOWN file: line:0 module:/usr/lib/libc.so.6]
<0x000055555558ec77> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x000055555555d197> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x0000555555560f77> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x000055555558cf50> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x000055555558cc91> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x000055555558b586> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x000055555558ca22> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x000055555555e393> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x000055555555fa3a> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x000055555556074b> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x0000555555560a9d> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x00005555555608d5> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x000055555556089a> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x0000555555560828> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x00005555555867fb> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x00005555555607fc> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
<0x00007ffff7c27cd0> [func:UNKNOWN file: line:0 module:/usr/lib/libc.so.6]
<0x00007ffff7c27d8a> [func:UNKNOWN file: line:0 module:/usr/lib/libc.so.6]
<0x000055555555ecd5> [func:UNKNOWN file: line:0 module:/home/psychopomp/coding/darkfi/main/fuzz2/hfuzz_target/x86_64-unknown-linux-gnu/release/serial-decode-string]
=====================================================================

View File

@@ -0,0 +1,33 @@
#!/usr/bin/env python3
"""
Take a binary file as input and prints its bytes as ordinals, formatted as an
array. The goal is to take a file that has caused a crash during binary fuzzing
and convert it into a unit test that can detect panic regressioins.
See darkfi/src/zkas/decoder.rs for example unit tests.
input:
- binary.bin
output
- [1, 2, 3, 5, 8, 11]
Now the output can be easily pasted into a unit test.
"""
import os.path
import sys
if len(sys.argv) != 2:
print(f"Usage: {__file__} <binary_file>")
exit(1)
if not os.path.isfile(sys.argv[1]):
print("Argument is not a file")
exit(2)
bytes = []
with open(sys.argv[1], "rb") as f:
while (byte := f.read(1)):
bytes.append(str(ord(byte)))
print(f"[{', '.join(bytes)}]")

View File

@@ -0,0 +1,15 @@
#/usr/bin/env bash
: '
Copies all ZK binary files (.zk.bin) from the main repository into a destination folder
in the fuzzing directory. This allows the compiled example binaries to be used as
test inputs for the fuzzer. This should in turn allow for more efficient fuzzing.
'
set -e
# Run from inside fuzz2 directory
CWD=$(pwd)
DST=$CWD/hfuzz_workspace/zkbinary-decode/input/
cd ..
mkdir -p $DST
find -name "*.zk.bin" -exec cp {} $CWD/hfuzz_workspace/zkbinary-decode/input/ \;
cd $CWD

View File

@@ -0,0 +1,34 @@
/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2023 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
extern crate darkfi_serial;
use honggfuzz::fuzz;
use darkfi_serial::deserialize;
fn main() {
loop {
fuzz!(|data: &[u8]| {
// Deserialize arbitrary data as a String
let _res: String = match deserialize::<String>(&data) {
Ok(..) => "".to_string(),
Err(..) => "".to_string(),
};
});
}
}

View File

@@ -0,0 +1,30 @@
/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2023 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
extern crate darkfi_serial;
use honggfuzz::fuzz;
use darkfi::zkas::ZkBinary;
fn main() {
loop {
fuzz!(|data: &[u8]| {
let _dec = ZkBinary::decode(data);
});
}
}