Skip to content

wip: Add OSS-Fuzz integration for ONNX#15382

Open
andife wants to merge 12 commits into
google:masterfrom
andife:master
Open

wip: Add OSS-Fuzz integration for ONNX#15382
andife wants to merge 12 commits into
google:masterfrom
andife:master

Conversation

@andife
Copy link
Copy Markdown

@andife andife commented Apr 17, 2026

Summary

Adds Python atheris fuzz targets for the ONNX library, covering the main parsing, validation, and transformation surfaces of the public API.

Fuzz targets

Target API exercised Input type
fuzz_checker checker.check_model(..., full_check=True) raw bytes (checker accepts bytes natively)
fuzz_model_loader load_model_from_string + graph traversal + check_model raw bytes
fuzz_parser parser.parse_model UTF-8 text (ONNX text format)
fuzz_shape_inference shape_inference.infer_shapes(..., check_type=True) raw bytes → deserialized ModelProto
fuzz_version_converter version_converter.convert_version raw bytes → ModelProto; tries version−1, version+1, and latest opset

Design notes

C++ extension instrumentation. ONNX's protobuf-based checker, shape inference engine, and version converter are implemented in C++. The build uses ONNX's own -DONNX_USE_ASAN=ON cmake option (introduced in the ONNX build system for exactly this purpose) together with the OSS-Fuzz $CFLAGS/$CXXFLAGS environment variables, so both the Python layer (via atheris) and the C++ extensions are instrumented under ASAN and UBSan.

Version converter seed corpus. make_seed_corpus.py generates a small set of valid ONNX models with edge cases relevant to version conversion (missing inputs, mixed opset versions) so the fuzzer starts with structurally valid inputs rather than from empty.

API contract differences. checker.check_model accepts Union[ModelProto, bytes, str, Path] and handles deserialization internally, so raw bytes are passed directly. shape_inference.infer_shapes accepts Union[ModelProto, str, Path] only, so the fuzzer deserializes first and passes the resulting ModelProto.

Testing

Built and ran locally with python infra/helper.py build_fuzzers onnx and python infra/helper.py run_fuzzer onnx <target>.

Signed-off-by: Andreas Fehlner <fehlner@arcor.de>
Signed-off-by: Andreas Fehlner <fehlner@arcor.de>
@github-actions
Copy link
Copy Markdown

andife is integrating a new project:
- Main repo: https://github.com/onnx/onnx
- Criticality score: 0.59387

@andife andife changed the title wip: onnx Add OSS-Fuzz integration for ONNX May 24, 2026
@andife andife changed the title Add OSS-Fuzz integration for ONNX wip: Add OSS-Fuzz integration for ONNX May 24, 2026
andife and others added 5 commits May 24, 2026 08:55
- fuzz_shape_inference: deserialize bytes to ModelProto before calling
  infer_shapes(), which does not accept raw bytes (was a no-op before)
- fuzz_checker: remove redundant exception union (Exception subsumes all)
- fuzz_parser: merge duplicate except branches into one
- fuzz_model_loader: traverse graph nodes/inputs/outputs and run
  check_model() after load to exercise more code paths
- fuzz_version_converter: replace random target version with model-aware
  selection (tries version-1, version+1, and latest opset)
- build.sh: forward CFLAGS/CXXFLAGS and set -DONNX_USE_ASAN=ON via
  CMAKE_ARGS so C++ extensions are sanitizer-instrumented; fix copyright
  year to 2026; add make_seed_corpus.py invocation
- project.yaml: add undefined (UBSan) sanitizer
- Add FuzzedDataProvider-based structured model construction
- Generate subgraph-bearing ops (If/Loop/Scan) to exercise the recursive visitor
- Sample strict_mode and check_type for broader API coverage
- Add RecursionError guard to keep fuzzer running on known DoS
- Move toggles to trailing byte so raw-bytes path preserves protobuf header
- Update copyright year to 2026 per OSS-Fuzz linter

Signed-off-by: MuhammedHussein17 <muhammedbussnies@gmail.com>
…store instrument_all

Signed-off-by: MuhammedHussein17 <muhammedbussnies@gmail.com>
- Remove @atheris.instrument_func from TestOneInput: atheris.instrument_all()
  in main() already covers it; the decorator is redundant and inconsistent
  with every other ONNX fuzzer in this directory.
- Raise sys.setrecursionlimit from 500 to 1000 (Python default): 500 was
  too conservative and risked spurious RecursionError suppression inside
  third-party code (Atheris internals, ONNX nanobind wrapper, protobuf
  runtime) that has nothing to do with the known shape_inference DoS.
  1000 still guards against the Python-level recursion path while
  eliminating false-positive drops.
- Update stale comment in _build_model that referenced the 500-frame limit.
…fuzzer

Improve fuzz_shape_inference.py with structured fuzzing
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.

2 participants