Commit graph

1 commit

Author SHA1 Message Date
trvon
470ed6f8b4
feat(fuzz): M31 — fuzz-prep emits Z3-derived harnesses + corpora
Build the static-analysis-driven fuzzing pipeline alongside the radare2
+ z3 work. fold's symbolic engine already proves sink feasibility; this
adds the path that retains the Z3 model, lowers it to libFuzzer
harnesses + seed corpora, and writes a findings.predicted.json bridge
so a future fold fuzz-run can promote crashes to ConcreteWitness
confidence.

* fold::fuzz value types (PathWitness, ParamWitness) + WitnessRecorder
  collector — process-local, lock-free hot-path check
* model_to_bytes — z3::model → little-endian std::byte at source width;
  pointer null-vs-nullable disambiguation
* harness_emitter — generates .harness.cc + .schema.json; honors
  is_c_linkage via `extern "C"` wrapper for C targets; nested-namespace
  emission for C++
* corpus_writer — packs witness bytes per harness layout, FNV-1a hash
  for filename, 3 canonical seeds (zeros / 0xFF / single byte)
* param_schema — schemaForFunction + recordSinkWitness +
  recordSinkWitnessWithModel; latter looks up each parameter's z3::expr
  via env->tryGet() and mines the model for byte payloads
* SafetyObserver: const SymbolicEnv* env added to onPointerDeref,
  onDivision, onTruncation, onSignedUnsignedConversion,
  onArraySubscript; encoder.cpp passes &env at every call site;
  CompositeSafetyObserver in scan_runner fans through
* null_deref, div_by_zero, int_overflow, int_truncation,
  sign_conversion now record witnesses with full model bytes;
  oob_access records schema-only (sat sites don't capture a model yet)
* fold fuzz-prep subcommand — runs scan in-process (workers can't
  ship recorder state), drains the recorder, emits one
  {harness,schema,corpus/} bundle per function

Smoke validation: 4 detectors on a 5-line C fixture produce
non-partial witnesses whose bytes are the exact magic values that
trigger each sink (flag=0xAB for null-deref; x=0 for div-by-zero;
a+b that overflows INT_MIN for int-overflow).

Tests: 34 → 37 (add test_model_to_bytes, test_harness_emitter,
test_corpus_writer). All green.

Also folds in a small worker-toolchain optimization that had been
sitting in the working tree: preloadHostToolchainEnv() avoids
repeated popen calls during worker init.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 14:21:43 -04:00