fuzz: Avoid dangling prevoutfetch threads after AFL fork
What changed, and why it matters
This commit fixes a fuzz-testing-only issue. When Bitcoin Core runs under AFL (a fuzzing tool), it forks the process after setup. Previously, worker threads created during initialization could become 'dangling' after the fork, causing crashes or unreliable fuzz results. The fix disables those extra threads during fuzzing, making tests more stable and deterministic. This does not affect normal Bitcoin node operation or end-user wallets.
No action needed for production deployments. For developers running AFL fuzzing, ensure this patch is applied to avoid spurious crashes and unreliable fuzzing results.
Security signals we found
thread lifecycle issue in test harness
AFL fork-after-initialization incompatibility
non-determinism/race condition in fuzzing
Evidence from the diff
In src/test/util/setup_common.cpp, the ChainTestingSetup constructor previously set worker_threads_num to 0 only when fuzz determinism was enabled, but left prevoutfetch_threads_num at its default (2). After an AFL fork, those prevoutfetch threads would not exist in the child process, leaving dangling thread handles and causing undefined behavior or crashes during fuzzing. The patch explicitly sets prevoutfetch_threads_num to 0 under the same condition, matching the existing worker_threads_num behavior.
Changed components
src/test/util/setup_common.cppfuzz test harnessChainTestingSetup constructorInspect captured patch +3 / −1
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index bcf63778..8c832976 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -307,8 +307,10 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts)
.check_block_index = 1,
.notifications = *m_node.notifications,
.signals = m_node.validation_signals.get(),
- // Use no worker threads while fuzzing to avoid non-determinism
+ // Use no worker threads while fuzzing to avoid racy non-determinism
+ // and dangling thread handles if AFL forks after initialization.
.worker_threads_num = EnableFuzzDeterminism() ? 0 : 2,
+ .prevoutfetch_threads_num = EnableFuzzDeterminism() ? 0 : 2,
};
if (opts.min_validation_cache) {
chainman_opts.script_execution_cache_bytes = 0;
Why this scored 21/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.