فهرست منبع

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>
greptile 2 سال پیش
والد
کامیت
d9d918b884

+ 6 - 3
fuzz/README.md

@@ -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 - 0
fuzz/honggfuzz/.gitignore

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

+ 41 - 0
fuzz/honggfuzz/Cargo.toml

@@ -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 - 0
fuzz/honggfuzz/README.md

@@ -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

+ 48 - 0
fuzz/honggfuzz/hfuzz_workspace/serial-decode-string/HONGGFUZZ.REPORT.TXT

@@ -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]
+=====================================================================

BIN
fuzz/honggfuzz/hfuzz_workspace/serial-decode-string/SIGABRT.PC.7ffff7c8e83c.STACK.c8ecc5e84.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebx.fuzz


+ 33 - 0
fuzz/honggfuzz/script/binary-to-bytearray.py

@@ -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)}]")

+ 15 - 0
fuzz/honggfuzz/script/generate-binary-corpus.sh

@@ -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

+ 34 - 0
fuzz/honggfuzz/src/serial_decode_string.rs

@@ -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(),
+            };
+        });
+    }
+}

+ 30 - 0
fuzz/honggfuzz/src/zkbinary_decode.rs

@@ -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);
+        });
+    }
+}