Skip to content

Add fuzz targets for BER/DER parsing and the Any conversion surface - #144

Open
dzatona wants to merge 2 commits into
rusticata:masterfrom
dzatona:feat-fuzz-targets
Open

Add fuzz targets for BER/DER parsing and the Any conversion surface#144
dzatona wants to merge 2 commits into
rusticata:masterfrom
dzatona:feat-fuzz-targets

Conversation

@dzatona

@dzatona dzatona commented Aug 16, 2026

Copy link
Copy Markdown

The README lists fuzzing among the crate's goals, but there is no fuzzing setup
in the tree. This adds a fuzz/ directory with four cargo-fuzz targets, laid out
the same way as der-parser and x509-parser. Nothing under src/ is touched.

Warning

On current master, three of the four targets crash within seconds — they
reproduce already-reported parser defects.
parse_ber_any and parse_der_any land on the REAL decoding defect in
#143, which a 12-byte BER-valid input reaches on its own; parse_collections
lands on the CheckDerConstraints for bool out-of-bounds index in #142, which
a two-byte input reaches. der_is_ber_subset is unaffected. To keep going past
the first artifact instead of stopping there, run with
-fork=1 -ignore_crashes=1.

The targets:

  • parse_ber_anyAny::from_ber, then all 43 Any::as_* conversions, then
    one level down through parse_content_ber.
  • parse_der_any — the DER counterpart, plus content decoded through
    DerParser::from_der_content for each concrete type. Separate from the BER
    one because DER's canonicality checks reach different code and want their own
    corpus.
  • der_is_ber_subset — a differential check rather than a panic hunt: anything
    that parses as DER must also parse as BER, to the same header, content and
    remainder. Separate so the others can be taken without also buying into that
    invariant.
  • parse_collectionsSequenceOf<T>, SetOf<T>, Vec<T>, HashSet<T>,
    BTreeSet<T>, AnyIterator in both modes, and the parsers emitted by
    DerSequence, BerSequence, DerSet, BerParserSequence and
    DerParserSequence, nested and OPTIONAL fields included.

parse_collections is a second commit, both because it is the larger half of the
diff and because of what it covers: the compatibility route FromDer
check_constraintsTryFrom<Any>. The other three reach concrete types only
through Any::as_* and <T as DerParser>::from_der_content, and neither of
those calls CheckDerConstraints, so every check_constraints impl in the crate
was unreachable from the rest of the set — a gap in shape rather than in depth.
As its own commit it is also easy to review, or drop, separately.

Running:

cargo +nightly fuzz build
cargo +nightly fuzz run parse_ber_any -- -max_total_time=300 -rss_limit_mb=4096

No corpus is committed; I can add a seed script if that would help. Build, fmt,
clippy and the crate's own test suite are clean, and the fuzz crate stays out
of the normal build.

Two choices for review:

  • fuzz/Cargo.lock is committed — pinning it makes a crash reproducible later,
    but neither der-parser nor x509-parser keeps one. I can omit it if you prefer.
  • Neither of those repos fuzzes in CI. A 60-second smoke run per target on PRs
    would catch harness rot; I can add .github/workflows/fuzz.yml if you want it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant