Fuzz the streaming input adapters against the contiguous one

The fast paths for contiguous input (bulk string scanning, multi-byte
loads, lazy position tracking) are taken only when parsing from a
pointer range; streams and non-contiguous iterators still read byte by
byte. The fuzzer drivers parsed only contiguous input, so a difference
between the two would ship unnoticed.

check_input_adapters() in fuzzer_common.hpp reads the input through a
std::istringstream, a std::list iterator range, and (on POSIX) a FILE*
from fmemopen, and asserts the same value, or the same exception id,
message and byte position, as for the pointer range. All seven drivers
call it; the JSON driver checks parse and accept, each with and without
ignore_comments. It replaces the stream check of the BON8 driver.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-14 16:33:08 +02:00
1 parent 7461a199b5
commit 9cbdcb5ed3
9 files changed
+264 -22

No files matched your search

+10 -1
View File
@@ -9,7 +9,16 @@ Each fuzzer driver (`tests/src/fuzzer-parse_*.cpp`) parses its input twice: once
once with exceptions. Both calls must agree. Where parsing with exceptions fails, the call without exceptions must
return a discarded value (or throw the same kind of non-parse error), and it must never throw a `parse_error`. Where
parsing succeeds, both calls must return the same value. The drivers then serialize the value, parse the result back,
and check that nothing was lost. The drivers check all of this with `assert`, so they refuse to build with `NDEBUG`.
and check that nothing was lost.
Finally, each driver reads the same input through the other input adapters: a `std::istringstream`, a non-contiguous
iterator range (`std::list<std::uint8_t>`), and, on POSIX systems, a `FILE*` from `fmemopen`. The pointer range takes the
fast paths for contiguous input (bulk string scanning, multi-byte loads, lazy position tracking), while the other
adapters read byte by byte. Every adapter must give the same value, or the same exception with the same id, message,
and byte position. The JSON driver checks this for `parse` and `accept`, each with and without `ignore_comments`. The
shared code is `check_input_adapters()` in `tests/src/fuzzer_common.hpp`.
The drivers check all of this with `assert`, so they refuse to build with `NDEBUG`.
## Corpus creation