Skip to content

ci: run fuzz_ffi_ops in the PR fuzz guard #102

@membphis

Description

@membphis

Background

qjson already has an FFI operation fuzz target: fuzz/fuzz_targets/fuzz_ffi_ops.rs.

This target is valuable because it drives the public FFI surface with randomized operation sequences instead of only fuzzing JSON parsing. It can exercise parse/get/cursor/object-entry/free interleavings, error paths, null handling, scratch-buffer reuse, and document/cursor lifetime behavior.

The current CI fuzz guard runs the parse-oriented targets, but does not run fuzz_ffi_ops:

  • fuzz_parse_eager
  • fuzz_depth
  • fuzz_parse_lazy

That leaves an existing FFI lifecycle fuzz target outside the PR regression guard.

Goal

Add the existing fuzz_ffi_ops target to the PR-length fuzz guard so CI continuously checks randomized FFI operation sequences.

This should improve confidence around the most fragile boundary in qjson: the Rust/LuaJIT FFI API and the lifecycle rules around documents, cursors, strings, and frees.

Why This Matters

Before this change, CI mainly checks that input JSON parsing is stable under fuzzing. That is useful, but it does not fully cover how callers use the FFI API after parsing.

The FFI surface has additional risks that parse-only fuzzing is unlikely to catch:

  • document and cursor lifetime mistakes
  • qjson_free interleavings
  • invalid or missing paths
  • null pointer handling
  • cursor field/index traversal edge cases
  • object entry access edge cases
  • get_str scratch-buffer reuse behavior
  • panic-barrier and error-code behavior under unusual call sequences

After this change, PR CI should also exercise randomized sequences of FFI calls against generated JSON inputs. This gives a cheap regression guard for lifecycle bugs without introducing a heavier sanitizer or Valgrind requirement into the normal PR path.

Proposed Scope

  • Add fuzz_ffi_ops to the existing CI fuzz job.
  • Use the same PR-length budget style as the current fuzz targets, for example:
cargo +nightly fuzz run fuzz_ffi_ops -- -max_total_time=60
  • Keep the command easy to run locally as well as in CI.
  • Update CONTRIBUTING.md so the local PR-length fuzz command list includes fuzz_ffi_ops.
  • Preserve the existing fuzz targets and their current behavior.

Non-Goals

  • Do not add a new fuzz target in this issue; the target already exists.
  • Do not expand PR fuzzing into a long-running fuzz campaign.
  • Do not increase the default PR fuzz budget beyond the current short regression-guard style.
  • Do not make ASan, Valgrind, or other heavier memory tools blocking as part of this issue.
  • Do not change the existing Miri, sanitizer, Lua, OpenResty, or package validation jobs.
  • Do not refactor the workflow structure unless it is necessary to add this command cleanly.

Acceptance Criteria

  • CI runs fuzz_ffi_ops as part of the PR fuzz guard.
  • A crash, panic, assertion failure, or libFuzzer failure from fuzz_ffi_ops fails the CI job.
  • Existing fuzz targets still run.
  • CONTRIBUTING.md documents the local command for fuzz_ffi_ops alongside the other PR-length fuzz commands.
  • The change stays focused on wiring the existing target into CI and local documentation.

Suggested Implementation Notes

The likely implementation is small:

  • Add one command to the existing fuzz section in .github/workflows/ci.yml.
  • Add the matching local command to the fuzzing section in CONTRIBUTING.md.

This keeps local and CI behavior aligned: developers can reproduce the same PR-length fuzz guard before pushing, while CI remains the final enforcement point.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions