---
name: clusterfuzzlite
description: Build, test, or update the iccDEV ClusterFuzzLite libFuzzer integration across ASan, UBSan, and MSan.
---

# ClusterFuzzLite Integration

Use this skill for `.clusterfuzzlite/**`,
`.github/workflows/ci-clusterfuzzlite.yml`, or the ClusterFuzzLite mode in
`.github/ci/cfl/build.sh`.

## Contract

- Treat libFuzzer as the single fuzzing engine and `address`, `undefined`, and
  `memory` as three separate sanitizer builds.
- Build all three in-process groups in ClusterFuzzLite: `core`
  (`profileparse`, `cmmapply`, `profilevisualize`, `writerserialize`),
  `formats` (`xmlparse`, `jsonparse`, `connectconfig`), and `assessment`
  (`pawgreport`).
- Forward the GitHub matrix group and patch mode through `CFL_EXTRA_*`; the
  official action builds a fresh `GITHUB_SHA` clone, so pre-step checkout file
  mutations do not reach the builder container.
- Forward and independently recompute the deterministic source-content digest.
  Reject a builder snapshot that differs from the Actions checkout; the
  official action may otherwise fall back to its current clone when a queued
  commit becomes unreachable after a history rewrite.
- Keep the CLI-fidelity wrappers in the local CFL smoke lane; they launch child
  tools and do not provide useful parent-process coverage feedback.
- Consume `CC`, `CXX`, `CFLAGS`, `CXXFLAGS`, and `LIB_FUZZING_ENGINE` from the
  OSS-Fuzz build environment. Do not combine hard-coded ASan flags with MSan.
- Require matching Clang 21 or Clang 22 compilers. The pinned OSS-Fuzz builder
  supplies Clang 22; do not allow an older fallback.
- Keep tools and zlib disabled. Enable XML/JSON only for targets that consume
  those libraries. The XML memory build must use the pinned instrumented
  libxml2 produced by the repository bootstrap.
- For `memory`, build the pinned MSan libc++ and libc++abi before compiling the
  fuzzers. Reject libstdc++ or a libc++ outside that runtime in `ldd`; for
  `xmlparse`, also reject libxml2 outside the bundled runtime. Replay the pinned
  #2687 artifact through every emitted target. Do not classify a dependency
  report from an uninstrumented runtime as iccDEV.
- Package tracked ICC, XML, and JSON fixtures only for the matching target
  family. Keep the shared profile/text options and profile/XML/JSON
  dictionaries aligned with explicit local CFL limits.
- Keep `cmmapply` control bytes outside the ICC header so direction, intent,
  and interpolation can mutate without corrupting the profile-size field.
- Keep a schema-shaped IccConnect seed and dedicated config dictionary. Drive
  `fromJson()`/`toJson()` round trips for top-level and nested `CIccCfg*`
  objects before adding another configuration target.
- Keep the workflow limited to manual dispatch and the nightly schedule. Manual
  dispatch defaults to one `address`/`core` smoke job; `run_mode=full` and the
  schedule use all nine group/sanitizer combinations.
- Keep the manual fuzz duration selectable as whole minutes from 2 through 45,
  validate it before the sanitizer matrix, pass it as the budget for each
  target group, and retain a 2-minute per-group budget for scheduled runs.
- Keep corpus pruning runnable after a fuzz finding. Keep coverage an explicit
  manual option that emits a ClusterFuzzLite artifact without broadening
  repository permissions.
- Keep one temporary CFL patch per open MSan issue. Attempt patches in order,
  report drift or already-integrated fixes, and continue the default workflow;
  reserve `--strict` for local patch-stack maintenance. Remove only the patch
  for an issue whose normal source fix has landed.
- Pin every action to a full commit SHA and the builder image to a digest.

## Expansion Order

After strengthening an existing target, prefer a multi-profile CMM chain,
separate XML/JSON serializers, and V5 display-observer conversion, in that
order. Add image or carrier targets only with instrumented MSan dependencies.
Do not copy the local research inventory wholesale; require a public
in-process seam, structured seed, and distinct attribution boundary.

## Local Validation

From an OSS-Fuzz checkout, run for each sanitizer in `address`, `undefined`,
and `memory`:

```bash
iccdev_source=/path/to/iccDEV
source_sha="$(git -C "$iccdev_source" rev-parse HEAD)"
source_digest="$("$iccdev_source/.github/scripts/iccdev-cfl-source-digest.sh" "$iccdev_source")"
python3 infra/helper.py build_image --external --pull "$iccdev_source"
python3 infra/helper.py build_fuzzers --external --clean \
  -e "ICCDEV_CFL_SOURCE_SHA=$source_sha" \
  -e "ICCDEV_CFL_SOURCE_DIGEST=$source_digest" \
  --engine libfuzzer --sanitizer SANITIZER "$iccdev_source"
python3 infra/helper.py check_build --external \
  --engine libfuzzer --sanitizer SANITIZER "$iccdev_source"
for target in profileparse cmmapply profilevisualize writerserialize \
  xmlparse jsonparse connectconfig pawgreport; do
  python3 infra/helper.py run_fuzzer --external \
    --engine libfuzzer --sanitizer SANITIZER \
    "$iccdev_source" "icc_${target}_fuzzer" -- -max_total_time=30
done
```

Also run:

```bash
bash -n .clusterfuzzlite/build.sh .github/ci/cfl/build.sh \
  .github/scripts/iccdev-clusterfuzzlite-config-tests.sh \
  .github/scripts/iccdev-clusterfuzzlite-target-tests.sh
.github/scripts/iccdev-clusterfuzzlite-config-tests.sh
.github/scripts/iccdev-fuzz-patch-check-tests.sh
.github/scripts/check-fuzz-patches.sh
ctest --test-dir Build -R '^iccdev\.clusterfuzzlite-(configuration|targets)$' \
  --output-on-failure --no-tests=error
actionlint -no-color .github/workflows/ci-clusterfuzzlite.yml
.github/scripts/preflight-safety-checks.sh --require-tools
```

Report each build, instrumentation check, and bounded run separately. An MSan
failure is not equivalent to an ASan or UBSan failure and must not be hidden by
fallback flags or an allowed-broken-target percentage. Record the resolved C++
runtime for every MSan fuzzer, the XML target's resolved libxml2, and the #2687
one-shot replay result.
