Skip to content

Commit 69e2d8c

Browse files
joostjagerclaude
andcommitted
Clean up fuzz crate: use panic=abort, add stdin_fuzz support, remove dylib
This commit makes three related changes to the fuzz infrastructure: 1. Set panic=abort on both dev and release profiles, and remove the dylib crate type (keeping rlib and staticlib). The dylib crate type was added in e28fd78 (2019) for a C-callable harness that was never implemented. Removing dylib is what enables panic=abort, since Rust forces panic=unwind on dylib crates. staticlib is retained as it is compatible with panic=abort. 2. Add stdin_fuzz support: a new Stdout logger, updated target template so that stdin_fuzz calls _test() with Stdout logging, and updated README with usage instructions. This allows reproducing crashes via piped input, useful for git bisect and AI-assisted debugging. 3. Update all fuzzer frontends (AFL, honggfuzz, libfuzzer, stdin_fuzz) to call the _test() functions directly instead of going through the _run() C wrappers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 153e57e commit 69e2d8c

File tree

75 files changed

+452
-361
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+452
-361
lines changed

fuzz/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,21 @@ cc = "1.0"
3939
members = ["."]
4040

4141
[profile.release]
42+
panic = "abort"
4243
lto = true
4344
codegen-units = 1
4445
debug-assertions = true
4546
overflow-checks = true
4647

4748
# When testing a large fuzz corpus, -O1 offers a nice speedup
4849
[profile.dev]
50+
panic = "abort"
4951
opt-level = 1
5052

5153
[lib]
5254
name = "lightning_fuzz"
5355
path = "src/lib.rs"
54-
crate-type = ["rlib", "dylib", "staticlib"]
56+
crate-type = ["rlib", "staticlib"]
5557

5658
[lints.rust.unexpected_cfgs]
5759
level = "forbid"

fuzz/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ mv hfuzz_workspace/fuzz_target/SIGABRT.PC.7ffff7e21ce1.STACK.[…].fuzz ./test_c
148148

149149
This will reproduce the failing fuzz input and yield a usable stack trace.
150150

151+
Alternatively, you can use the `stdin_fuzz` feature to pipe the crash input directly without
152+
creating test case files on disk:
153+
154+
```shell
155+
echo -ne '\x2d\x31\x36\x38\x37\x34\x09\x01...' | RUSTFLAGS="--cfg=fuzzing --cfg=secp256k1_fuzz --cfg=hashes_fuzz" cargo run --features stdin_fuzz --bin full_stack_target
156+
```
157+
158+
Panics will abort the process directly (the crate uses `panic = "abort"`), resulting in a
159+
non-zero exit code. Piping via stdin is useful for reproducing crashes during `git bisect` or
160+
when working with AI agents that can construct and pipe byte sequences directly.
151161

152162
## How do I add a new fuzz test?
153163

fuzz/src/bin/base32_target.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
2424

2525
extern crate lightning_fuzz;
2626
use lightning_fuzz::base32::*;
27+
use lightning_fuzz::utils::test_logger;
2728

2829
#[cfg(feature = "afl")]
2930
#[macro_use] extern crate afl;
3031
#[cfg(feature = "afl")]
3132
fn main() {
3233
fuzz!(|data| {
33-
base32_run(data.as_ptr(), data.len());
34+
base32_test(&data, test_logger::DevNull {});
3435
});
3536
}
3637

@@ -40,7 +41,7 @@ fn main() {
4041
fn main() {
4142
loop {
4243
fuzz!(|data| {
43-
base32_run(data.as_ptr(), data.len());
44+
base32_test(&data, test_logger::DevNull {});
4445
});
4546
}
4647
}
@@ -49,7 +50,7 @@ fn main() {
4950
#[macro_use] extern crate libfuzzer_sys;
5051
#[cfg(feature = "libfuzzer_fuzz")]
5152
fuzz_target!(|data: &[u8]| {
52-
base32_run(data.as_ptr(), data.len());
53+
base32_test(data, test_logger::DevNull {});
5354
});
5455

5556
#[cfg(feature = "stdin_fuzz")]
@@ -58,7 +59,7 @@ fn main() {
5859

5960
let mut data = Vec::with_capacity(8192);
6061
std::io::stdin().read_to_end(&mut data).unwrap();
61-
base32_run(data.as_ptr(), data.len());
62+
base32_test(&data, lightning_fuzz::utils::test_logger::Stdout {});
6263
}
6364

6465
#[test]
@@ -70,7 +71,7 @@ fn run_test_cases() {
7071
use std::sync::{atomic, Arc};
7172
{
7273
let data: Vec<u8> = vec![0];
73-
base32_run(data.as_ptr(), data.len());
74+
base32_test(&data, test_logger::DevNull {});
7475
}
7576
let mut threads = Vec::new();
7677
let threads_running = Arc::new(atomic::AtomicUsize::new(0));

fuzz/src/bin/bech32_parse_target.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
2424

2525
extern crate lightning_fuzz;
2626
use lightning_fuzz::bech32_parse::*;
27+
use lightning_fuzz::utils::test_logger;
2728

2829
#[cfg(feature = "afl")]
2930
#[macro_use] extern crate afl;
3031
#[cfg(feature = "afl")]
3132
fn main() {
3233
fuzz!(|data| {
33-
bech32_parse_run(data.as_ptr(), data.len());
34+
bech32_parse_test(&data, test_logger::DevNull {});
3435
});
3536
}
3637

@@ -40,7 +41,7 @@ fn main() {
4041
fn main() {
4142
loop {
4243
fuzz!(|data| {
43-
bech32_parse_run(data.as_ptr(), data.len());
44+
bech32_parse_test(&data, test_logger::DevNull {});
4445
});
4546
}
4647
}
@@ -49,7 +50,7 @@ fn main() {
4950
#[macro_use] extern crate libfuzzer_sys;
5051
#[cfg(feature = "libfuzzer_fuzz")]
5152
fuzz_target!(|data: &[u8]| {
52-
bech32_parse_run(data.as_ptr(), data.len());
53+
bech32_parse_test(data, test_logger::DevNull {});
5354
});
5455

5556
#[cfg(feature = "stdin_fuzz")]
@@ -58,7 +59,7 @@ fn main() {
5859

5960
let mut data = Vec::with_capacity(8192);
6061
std::io::stdin().read_to_end(&mut data).unwrap();
61-
bech32_parse_run(data.as_ptr(), data.len());
62+
bech32_parse_test(&data, lightning_fuzz::utils::test_logger::Stdout {});
6263
}
6364

6465
#[test]
@@ -70,7 +71,7 @@ fn run_test_cases() {
7071
use std::sync::{atomic, Arc};
7172
{
7273
let data: Vec<u8> = vec![0];
73-
bech32_parse_run(data.as_ptr(), data.len());
74+
bech32_parse_test(&data, test_logger::DevNull {});
7475
}
7576
let mut threads = Vec::new();
7677
let threads_running = Arc::new(atomic::AtomicUsize::new(0));

fuzz/src/bin/bolt11_deser_target.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
2424

2525
extern crate lightning_fuzz;
2626
use lightning_fuzz::bolt11_deser::*;
27+
use lightning_fuzz::utils::test_logger;
2728

2829
#[cfg(feature = "afl")]
2930
#[macro_use] extern crate afl;
3031
#[cfg(feature = "afl")]
3132
fn main() {
3233
fuzz!(|data| {
33-
bolt11_deser_run(data.as_ptr(), data.len());
34+
bolt11_deser_test(&data, test_logger::DevNull {});
3435
});
3536
}
3637

@@ -40,7 +41,7 @@ fn main() {
4041
fn main() {
4142
loop {
4243
fuzz!(|data| {
43-
bolt11_deser_run(data.as_ptr(), data.len());
44+
bolt11_deser_test(&data, test_logger::DevNull {});
4445
});
4546
}
4647
}
@@ -49,7 +50,7 @@ fn main() {
4950
#[macro_use] extern crate libfuzzer_sys;
5051
#[cfg(feature = "libfuzzer_fuzz")]
5152
fuzz_target!(|data: &[u8]| {
52-
bolt11_deser_run(data.as_ptr(), data.len());
53+
bolt11_deser_test(data, test_logger::DevNull {});
5354
});
5455

5556
#[cfg(feature = "stdin_fuzz")]
@@ -58,7 +59,7 @@ fn main() {
5859

5960
let mut data = Vec::with_capacity(8192);
6061
std::io::stdin().read_to_end(&mut data).unwrap();
61-
bolt11_deser_run(data.as_ptr(), data.len());
62+
bolt11_deser_test(&data, lightning_fuzz::utils::test_logger::Stdout {});
6263
}
6364

6465
#[test]
@@ -70,7 +71,7 @@ fn run_test_cases() {
7071
use std::sync::{atomic, Arc};
7172
{
7273
let data: Vec<u8> = vec![0];
73-
bolt11_deser_run(data.as_ptr(), data.len());
74+
bolt11_deser_test(&data, test_logger::DevNull {});
7475
}
7576
let mut threads = Vec::new();
7677
let threads_running = Arc::new(atomic::AtomicUsize::new(0));

fuzz/src/bin/chanmon_consistency_target.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
2424

2525
extern crate lightning_fuzz;
2626
use lightning_fuzz::chanmon_consistency::*;
27+
use lightning_fuzz::utils::test_logger;
2728

2829
#[cfg(feature = "afl")]
2930
#[macro_use] extern crate afl;
3031
#[cfg(feature = "afl")]
3132
fn main() {
3233
fuzz!(|data| {
33-
chanmon_consistency_run(data.as_ptr(), data.len());
34+
chanmon_consistency_test(&data, test_logger::DevNull {});
3435
});
3536
}
3637

@@ -40,7 +41,7 @@ fn main() {
4041
fn main() {
4142
loop {
4243
fuzz!(|data| {
43-
chanmon_consistency_run(data.as_ptr(), data.len());
44+
chanmon_consistency_test(&data, test_logger::DevNull {});
4445
});
4546
}
4647
}
@@ -49,7 +50,7 @@ fn main() {
4950
#[macro_use] extern crate libfuzzer_sys;
5051
#[cfg(feature = "libfuzzer_fuzz")]
5152
fuzz_target!(|data: &[u8]| {
52-
chanmon_consistency_run(data.as_ptr(), data.len());
53+
chanmon_consistency_test(data, test_logger::DevNull {});
5354
});
5455

5556
#[cfg(feature = "stdin_fuzz")]
@@ -58,7 +59,7 @@ fn main() {
5859

5960
let mut data = Vec::with_capacity(8192);
6061
std::io::stdin().read_to_end(&mut data).unwrap();
61-
chanmon_consistency_run(data.as_ptr(), data.len());
62+
chanmon_consistency_test(&data, lightning_fuzz::utils::test_logger::Stdout {});
6263
}
6364

6465
#[test]
@@ -70,7 +71,7 @@ fn run_test_cases() {
7071
use std::sync::{atomic, Arc};
7172
{
7273
let data: Vec<u8> = vec![0];
73-
chanmon_consistency_run(data.as_ptr(), data.len());
74+
chanmon_consistency_test(&data, test_logger::DevNull {});
7475
}
7576
let mut threads = Vec::new();
7677
let threads_running = Arc::new(atomic::AtomicUsize::new(0));

fuzz/src/bin/chanmon_deser_target.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
2424

2525
extern crate lightning_fuzz;
2626
use lightning_fuzz::chanmon_deser::*;
27+
use lightning_fuzz::utils::test_logger;
2728

2829
#[cfg(feature = "afl")]
2930
#[macro_use] extern crate afl;
3031
#[cfg(feature = "afl")]
3132
fn main() {
3233
fuzz!(|data| {
33-
chanmon_deser_run(data.as_ptr(), data.len());
34+
chanmon_deser_test(&data, test_logger::DevNull {});
3435
});
3536
}
3637

@@ -40,7 +41,7 @@ fn main() {
4041
fn main() {
4142
loop {
4243
fuzz!(|data| {
43-
chanmon_deser_run(data.as_ptr(), data.len());
44+
chanmon_deser_test(&data, test_logger::DevNull {});
4445
});
4546
}
4647
}
@@ -49,7 +50,7 @@ fn main() {
4950
#[macro_use] extern crate libfuzzer_sys;
5051
#[cfg(feature = "libfuzzer_fuzz")]
5152
fuzz_target!(|data: &[u8]| {
52-
chanmon_deser_run(data.as_ptr(), data.len());
53+
chanmon_deser_test(data, test_logger::DevNull {});
5354
});
5455

5556
#[cfg(feature = "stdin_fuzz")]
@@ -58,7 +59,7 @@ fn main() {
5859

5960
let mut data = Vec::with_capacity(8192);
6061
std::io::stdin().read_to_end(&mut data).unwrap();
61-
chanmon_deser_run(data.as_ptr(), data.len());
62+
chanmon_deser_test(&data, lightning_fuzz::utils::test_logger::Stdout {});
6263
}
6364

6465
#[test]
@@ -70,7 +71,7 @@ fn run_test_cases() {
7071
use std::sync::{atomic, Arc};
7172
{
7273
let data: Vec<u8> = vec![0];
73-
chanmon_deser_run(data.as_ptr(), data.len());
74+
chanmon_deser_test(&data, test_logger::DevNull {});
7475
}
7576
let mut threads = Vec::new();
7677
let threads_running = Arc::new(atomic::AtomicUsize::new(0));

fuzz/src/bin/feature_flags_target.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ compile_error!("Fuzz targets need cfg=secp256k1_fuzz");
2424

2525
extern crate lightning_fuzz;
2626
use lightning_fuzz::feature_flags::*;
27+
use lightning_fuzz::utils::test_logger;
2728

2829
#[cfg(feature = "afl")]
2930
#[macro_use] extern crate afl;
3031
#[cfg(feature = "afl")]
3132
fn main() {
3233
fuzz!(|data| {
33-
feature_flags_run(data.as_ptr(), data.len());
34+
feature_flags_test(&data, test_logger::DevNull {});
3435
});
3536
}
3637

@@ -40,7 +41,7 @@ fn main() {
4041
fn main() {
4142
loop {
4243
fuzz!(|data| {
43-
feature_flags_run(data.as_ptr(), data.len());
44+
feature_flags_test(&data, test_logger::DevNull {});
4445
});
4546
}
4647
}
@@ -49,7 +50,7 @@ fn main() {
4950
#[macro_use] extern crate libfuzzer_sys;
5051
#[cfg(feature = "libfuzzer_fuzz")]
5152
fuzz_target!(|data: &[u8]| {
52-
feature_flags_run(data.as_ptr(), data.len());
53+
feature_flags_test(data, test_logger::DevNull {});
5354
});
5455

5556
#[cfg(feature = "stdin_fuzz")]
@@ -58,7 +59,7 @@ fn main() {
5859

5960
let mut data = Vec::with_capacity(8192);
6061
std::io::stdin().read_to_end(&mut data).unwrap();
61-
feature_flags_run(data.as_ptr(), data.len());
62+
feature_flags_test(&data, lightning_fuzz::utils::test_logger::Stdout {});
6263
}
6364

6465
#[test]
@@ -70,7 +71,7 @@ fn run_test_cases() {
7071
use std::sync::{atomic, Arc};
7172
{
7273
let data: Vec<u8> = vec![0];
73-
feature_flags_run(data.as_ptr(), data.len());
74+
feature_flags_test(&data, test_logger::DevNull {});
7475
}
7576
let mut threads = Vec::new();
7677
let threads_running = Arc::new(atomic::AtomicUsize::new(0));

0 commit comments

Comments
 (0)