The fuzz build provides four Clang/libFuzzer targets:
pjson_fuzz_parseexercises strict DOM parsing only, while varying duplicate-key policy and bounded parse budgets across the same bytes.pjson_fuzz_streamcompares DOM, buffered stream, SAX-buffer, and chunked SAX-stream behavior under the same option variants.pjson_fuzz_schemaparses a schema and instance and verifies agreement between both validation overloads. Its input isschema, one newline byte, theninstance; inputs without a newline are split at their midpoint.pjson_fuzz_patchsplits its input intodocumentandpatch, then drives RFC 6902 JSON Patch when the second half parses as an array, otherwise RFC 7396 Merge Patch. It checks atomic failure and stable serialization after success.
Inputs under corpus/patch/ intentionally cover both successful and failing
patch documents so coverage includes rollback and diagnostic paths.
Run the bounded smoke used in CI with:
./build.sh --fuzz --autoOn Linux and macOS, build.sh --fuzz probes for a usable Clang/libFuzzer
toolchain, configures -DPJSON_BUILD_FUZZERS=ON, builds all four harnesses,
and replays each checked-in seed corpus with deterministic bounds:
-runs=1000-seed=1337-max_len=4096-timeout=5
Checked-in seeds are read-only inputs under corpus/; generated corpus entries
and failure artifacts go under the ignored out/fuzz-corpus/ and
out/fuzz-artifacts/ trees. To preserve a useful failure or coverage
discovery, minimize it and copy the result into the matching checked-in corpus
with a descriptive name.
Direct CMake builds use -DPJSON_BUILD_FUZZERS=ON.
Local libFuzzer builds rely on Clang plus a working -fsanitize=fuzzer runtime:
cmake -S . -B out/build-fuzz \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DPJSON_BUILD_TESTS=OFF \
-DPJSON_BUILD_EXAMPLES=OFF \
-DPJSON_BUILD_BENCHMARKS=OFF \
-DPJSON_BUILD_FUZZERS=ON
cmake --build out/build-fuzz --parallel --target \
pjson_fuzz_parse pjson_fuzz_stream pjson_fuzz_schema pjson_fuzz_patchExternal-engine builds pass linker input through the cache variable
PJSON_FUZZING_ENGINE. When that variable is non-empty, fuzz/CMakeLists.txt
does not require Clang's bundled libFuzzer runtime and instead splits the
provided shell-style engine string before linking each harness. This is the
path used by repository-local OSS-Fuzz integration:
cmake -S . -B out/build-fuzz \
-DPJSON_BUILD_TESTS=OFF \
-DPJSON_BUILD_EXAMPLES=OFF \
-DPJSON_BUILD_BENCHMARKS=OFF \
-DPJSON_BUILD_FUZZERS=ON \
-DPJSON_FUZZING_ENGINE="${LIB_FUZZING_ENGINE}"Repository-local OSS-Fuzz wiring is under ../oss-fuzz/. Its build script
configures PJSON_BUILD_FUZZERS=ON, passes
PJSON_FUZZING_ENGINE="${LIB_FUZZING_ENGINE}", builds all four harnesses, and
packages per-target seed corpora from fuzz/corpus/{parse,stream,schema,patch}.