This directory contains fuzz targets for testing Unicity's parsing and deserialization code.
- fuzz_block_header - Tests block header deserialization (100-byte headers)
- fuzz_varint - Tests variable-length integer encoding/decoding
- fuzz_messages - Tests all network message types (VERSION, HEADERS, INV, etc.)
- fuzz_message_header - Tests message header parsing (magic, command, checksum)
-
fuzz_asert_difficulty - Tests ASERT difficulty algorithm for overflow, clamping, and determinism
- Exercises 512-bit arithmetic in CalculateASERT (src/chain/pow.cpp:40-129)
- Tests overflow protection, exponent calculation, polynomial approximation
- Validates range clamping (result ≤ powLimit, result ≥ 1)
- Verifies determinism (same inputs → same output across multiple runs)
- Runs at high speed (no blockchain state required)
-
fuzz_randomx_pow - Tests RandomX proof-of-work verification and VM lifecycle
- Exercises VM cache management, epoch transitions, and hash verification
- Tests mode confusion (FULL vs COMMITMENT_ONLY vs MINING)
- Validates deterministic hash computation and commitment verification
- Tests VM reference counting and thread-local cache eviction
- Verifies nBits validation and invalid header handling
- fuzz_netaddr_parsing - Tests IPv4/IPv6 address parsing and normalization
- Exercises ValidateAndNormalizeIP and ParseIPPort functions
- Tests IPv4-mapped IPv6 normalization (prevents ban evasion)
- Validates port number edge cases (0, 65535, overflow)
- Tests bracket handling for IPv6 addresses
- Verifies idempotent normalization and determinism
-
fuzz_header_validation - Tests block header validation (CheckBlockHeader, ContextualCheckBlockHeader)
- Exercises CheckBlockHeader (full RandomX PoW verification)
- Tests ContextualCheckBlockHeader (difficulty, timestamps, version)
- Validates CheckHeadersPoW (fast commitment-only checks)
- Tests CheckHeadersAreContinuous (chain continuity)
- Verifies CalculateHeadersWork (cumulative work calculation)
- Validates edge cases (timestamps, nBits values)
- Verifies deterministic validation behavior
-
fuzz_block_locator - Tests block locator generation for header sync
- Exercises Chain::GetLocator with various chain heights
- Tests locator size bounds (prevents DoS via unbounded locators)
- Validates step calculation (exponential backoff)
- Tests edge cases (genesis, null tip, very tall chains)
- Verifies deterministic locator generation
- Tests locator hash uniqueness and ordering
- Validates with synthetic chain structures
- fuzz_chain_reorg - Tests chain reorganization, orphan processing, and InvalidateBlock cascades
- Exercises 316+ conditional branches in chainstate_manager.cpp
- Tests competing forks, reorg depth limits, orphan resolution
- Validates chain selection and suspicious reorg detection
- Runs at ~270k exec/s (bypasses expensive PoW for speed)
-
fuzz_atomic_write - Tests atomic file write operations
- Exercises atomic_write_file with random data sizes, filenames, and permissions
- Tests path traversal sanitization and filename validation
- Validates write-to-temp + fsync + atomic-rename pattern
- Verifies proper cleanup on all error paths
- Tests file mode handling (0-0777 permission bits)
-
fuzz_read_file - Tests file reading operations with malformed data
- Exercises read_file and read_file_string with arbitrary binary data
- Tests 100MB size limit enforcement (prevents DoS)
- Validates permission error handling (readonly files)
- Tests special characters in filenames
- Verifies null byte handling in string reads
-
fuzz_lock_directory - Tests directory locking for multi-process safety
- Exercises LockDirectory, UnlockDirectory, and ReleaseAllDirectoryLocks
- Tests malformed lock files and concurrent lock attempts
- Validates path traversal protection
- Tests readonly directory handling
- Verifies lock release on process exit
- Tests double-lock scenarios and lock conflicts
- Clang compiler (for libFuzzer support)
- CMake 3.20+
- Boost libraries
# Create build directory
mkdir -p build-fuzz
cd build-fuzz
# Configure with fuzzing enabled
cmake .. \
-DENABLE_FUZZING=ON \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_BUILD_TYPE=RelWithDebInfo
# Build
make -j$(nproc)# Run for 60 seconds with 4 parallel jobs
./fuzz/fuzz_block_header -max_total_time=60 -jobs=4
# Run with corpus directory (saves interesting inputs)
mkdir -p corpus/block_header
./fuzz/fuzz_block_header corpus/block_header -max_total_time=300
# Run chain reorganization fuzzer (with seed corpus)
python3 ../fuzz/generate_chain_seeds.py # Creates fuzz/corpus/
./fuzz/fuzz_chain_reorg ../fuzz/corpus/ -max_total_time=300
# Run with AddressSanitizer for better bug detection
cmake .. -DENABLE_FUZZING=ON -DCMAKE_CXX_COMPILER=clang++ -DSANITIZE=address
make -j$(nproc)
./fuzz/fuzz_messages corpus/messages -max_total_time=600-max_total_time=N- Run for N seconds-jobs=N- Run N parallel fuzzing jobs-max_len=N- Maximum input length-dict=file.dict- Use dictionary file for structured inputs-print_final_stats=1- Show coverage statistics-help=1- Show all options
OSS-Fuzz is Google's continuous fuzzing service for open source projects. It provides:
- 24/7 fuzzing infrastructure
- Automatic bug reporting
- Multiple sanitizers (ASan, UBSan, MSan)
- Multiple fuzzing engines (libFuzzer, AFL++, Hongfuzz)
- Coverage tracking
The ../oss-fuzz/ directory contains:
- project.yaml - Project configuration and contacts
- Dockerfile - Build environment setup
- build.sh - Build script for OSS-Fuzz infrastructure
You can test the OSS-Fuzz build locally before submission:
# Clone OSS-Fuzz
git clone https://github.com/google/oss-fuzz.git
cd oss-fuzz
# Create project directory
mkdir -p projects/unicity
cp ../unicity/oss-fuzz/* projects/unicity/
# Build with OSS-Fuzz
python infra/helper.py build_image unicity
python infra/helper.py build_fuzzers unicity
# Run a fuzzer
python infra/helper.py run_fuzzer unicity fuzz_block_headerTo get continuous fuzzing from Google:
- Fork the OSS-Fuzz repository
- Add your project files to
projects/unicity/ - Test locally with the commands above
- Submit a pull request to OSS-Fuzz
- Google will review and approve
See: https://google.github.io/oss-fuzz/getting-started/new-project-guide/
- Start small - Run fuzzers for a few minutes locally first
- Use corpora - Save and reuse interesting inputs
- Run with sanitizers - ASan, UBSan catch memory bugs
- Parallel fuzzing - Use multiple jobs for faster coverage
- Check regularly - Even 5 minutes of fuzzing can find bugs
- Minimize crashes - Use
libFuzzer -minimize_crash=1to reduce crash cases
If a fuzzer finds a crash:
==12345==ERROR: AddressSanitizer: heap-buffer-overflow
The crashing input is saved to crash-* file. To reproduce:
./fuzz/fuzz_block_header crash-abc123LibFuzzer reports coverage:
#12345 NEW cov: 456 ft: 789 corp: 23/1234b
- cov: Code coverage (number of edges)
- ft: Feature coverage (interesting behaviors)
- corp: Corpus size
These fuzz targets test:
- Buffer overflow vulnerabilities
- Integer overflows in VarInt parsing
- DoS via excessive allocations
- Malformed message handling
- Round-trip serialization consistency
All parsing code should handle arbitrary untrusted input without crashing.