fuzzprep 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. fuzzprep/__init__.py +3 -0
  2. fuzzprep/__main__.py +4 -0
  3. fuzzprep/agents/harness_builder/SKILL.md +156 -0
  4. fuzzprep/agents/library_builder/SKILL.md +147 -0
  5. fuzzprep/agents/scripts/check_build.sh +87 -0
  6. fuzzprep/agents/scripts/check_build_in_container.sh +73 -0
  7. fuzzprep/agents/scripts/check_dockerfile_from_scratch.sh +33 -0
  8. fuzzprep/cli.py +1109 -0
  9. fuzzprep/core/__init__.py +0 -0
  10. fuzzprep/core/agent_stream.py +304 -0
  11. fuzzprep/core/files.py +35 -0
  12. fuzzprep/core/paths.py +25 -0
  13. fuzzprep/core/reporting.py +218 -0
  14. fuzzprep/core/repos.py +217 -0
  15. fuzzprep/core/resources.py +41 -0
  16. fuzzprep/core/subprocesses.py +197 -0
  17. fuzzprep/feature_extractor/__init__.py +0 -0
  18. fuzzprep/feature_extractor/benchmark_yaml.py +92 -0
  19. fuzzprep/feature_extractor/extraction.py +184 -0
  20. fuzzprep/feature_extractor/models.py +96 -0
  21. fuzzprep/feature_extractor/native/.clang-format +1 -0
  22. fuzzprep/feature_extractor/native/CMakeLists.txt +90 -0
  23. fuzzprep/feature_extractor/native/include/feature_extractor.hpp +136 -0
  24. fuzzprep/feature_extractor/native/src/extraction_action.cpp +294 -0
  25. fuzzprep/feature_extractor/native/src/json_writer.cpp +154 -0
  26. fuzzprep/feature_extractor/native/src/macro_callbacks.cpp +75 -0
  27. fuzzprep/feature_extractor/native/src/main.cpp +130 -0
  28. fuzzprep/feature_extractor/native_build.py +99 -0
  29. fuzzprep/library_builder/__init__.py +0 -0
  30. fuzzprep/library_builder/agents.py +472 -0
  31. fuzzprep/library_builder/analysis.py +145 -0
  32. fuzzprep/library_builder/build_parameters.py +158 -0
  33. fuzzprep/library_builder/dependency_resolution.py +139 -0
  34. fuzzprep/library_builder/environments/__init__.py +0 -0
  35. fuzzprep/library_builder/environments/base.py +89 -0
  36. fuzzprep/library_builder/environments/gate.py +96 -0
  37. fuzzprep/library_builder/environments/local.py +205 -0
  38. fuzzprep/library_builder/environments/oss_fuzz.py +485 -0
  39. fuzzprep/library_builder/environments/verification.py +125 -0
  40. fuzzprep/library_builder/exploration.py +217 -0
  41. fuzzprep/library_builder/generation.py +325 -0
  42. fuzzprep/library_builder/harness_explorer.py +257 -0
  43. fuzzprep/library_builder/models.py +169 -0
  44. fuzzprep/library_builder/package_names.json +33 -0
  45. fuzzprep/library_builder/package_names.py +40 -0
  46. fuzzprep/library_builder/scripts.py +389 -0
  47. fuzzprep/library_builder/stats.py +102 -0
  48. fuzzprep/library_builder/symbol_patterns.json +65 -0
  49. fuzzprep/library_builder/timeouts.py +14 -0
  50. fuzzprep/library_builder/workspace.py +250 -0
  51. fuzzprep-0.1.0.dist-info/METADATA +255 -0
  52. fuzzprep-0.1.0.dist-info/RECORD +56 -0
  53. fuzzprep-0.1.0.dist-info/WHEEL +4 -0
  54. fuzzprep-0.1.0.dist-info/entry_points.txt +3 -0
  55. fuzzprep-0.1.0.dist-info/licenses/LICENSE +202 -0
  56. fuzzprep-0.1.0.dist-info/licenses/THIRD_PARTY_NOTICES.md +52 -0
@@ -0,0 +1,250 @@
1
+ """The project workspace: one directory layout, materialized once, verified, then shipped.
2
+
3
+ `.fuzzprep/<project>/` is the project, not a scratch area translated into output later.
4
+ It holds a real OSS-Fuzz project (`project.yaml`, `Dockerfile`, `build.sh`) plus the build and
5
+ harness-compile scripts, and generation copies it verbatim, so what ships is what was
6
+ verified, including any repair an agent applied.
7
+
8
+ Both environments materialize the same layout. Only the oss-fuzz target builds an image from
9
+ the Dockerfile here.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from pathlib import Path
15
+
16
+ from fuzzprep.core.files import write_executable
17
+ from fuzzprep.library_builder.build_parameters import BuildParameters
18
+ from fuzzprep.library_builder.models import (
19
+ AnalysisResult,
20
+ AutotoolsSetup,
21
+ Language,
22
+ LinkConfiguration,
23
+ )
24
+ from fuzzprep.library_builder.scripts import (
25
+ HARNESS_SOURCE_DIR,
26
+ build_harness_script,
27
+ build_harnesses_script,
28
+ write_default_fuzzer,
29
+ )
30
+
31
+ _AUTOTOOLS_PACKAGES = ("autoconf", "automake", "libtool", "pkg-config")
32
+
33
+ # ubuntu-24-04, not the Focal-based default tag: Focal's bear (2.4.3) mishandles the
34
+ # `bear -- <command>` form exploration.py builds, passing `--` on as if it were the command.
35
+ # Ubuntu 24.04 ships bear 3.x, which handles it.
36
+ DEFAULT_BASE_IMAGE = "gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04"
37
+
38
+ # The one place this apt-get invocation text is spelled out. Shared with generation's
39
+ # bear-stripping and with inject_apt_packages below.
40
+ APT_INSTALL_PREFIX = "RUN apt-get update && apt-get install -y --no-install-recommends"
41
+
42
+ # build.sh is what OSS-Fuzz's `compile` runs and what check_build.sh runs before asserting,
43
+ # so the two cannot disagree about what building this project means. $SCRIPT_DIR rather than
44
+ # $SRC: they are the same path in the container, and $SRC does not exist on the host.
45
+ _BUILD_SH = (
46
+ "#!/bin/bash\n"
47
+ "set -euo pipefail\n"
48
+ "\n"
49
+ 'SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"\n'
50
+ "\n"
51
+ 'echo "=== build_library.sh ==="\n'
52
+ '"$SCRIPT_DIR/build_library.sh"\n'
53
+ 'echo "=== compile_harnesses.sh ==="\n'
54
+ '"$SCRIPT_DIR/compile_harnesses.sh"\n'
55
+ )
56
+
57
+
58
+ def materialize(
59
+ workdir: Path,
60
+ analysis: AnalysisResult,
61
+ *,
62
+ parameters: BuildParameters,
63
+ base_image: str | None = None,
64
+ ) -> None:
65
+ """Write the full project layout into workdir, except build_library.sh.
66
+
67
+ Every file here is fixed or derives only from static analysis, so this runs before any
68
+ build attempt. That is what leaves a repair agent something runnable even when no build
69
+ system was identified: the gate it is told to run needs compile_harnesses.sh and a harness
70
+ source to exist regardless.
71
+
72
+ build_library.sh is written by exploration.write_build_library_script, which owns the
73
+ source-layout decision and rewrites it on each attempt.
74
+ """
75
+ workdir.mkdir(parents=True, exist_ok=True)
76
+ write_project_yaml(workdir, analysis)
77
+ write_dockerfile(workdir, analysis, include_bear=True, base_image=base_image)
78
+ write_build_sh(workdir)
79
+ write_harness_scripts(workdir, analysis.language, parameters=parameters)
80
+
81
+
82
+ def write_harness_scripts(
83
+ workdir: Path, language: Language, *, parameters: BuildParameters
84
+ ) -> Path:
85
+ """Write compile_harness.sh, compile_harnesses.sh, and a default harness source.
86
+
87
+ The stub gives the gate's non-empty-$OUT assertion something to find before harness-link
88
+ discovery has run. Discovery later rewrites compile_harness.sh with each flag it resolves.
89
+ """
90
+ harness_source_dir = workdir / HARNESS_SOURCE_DIR
91
+ harness_source_dir.mkdir(parents=True, exist_ok=True)
92
+ write_default_fuzzer(harness_source_dir, language)
93
+ write_executable(
94
+ workdir / "compile_harness.sh",
95
+ build_harness_script(
96
+ LinkConfiguration(),
97
+ harness_cflags=parameters.harness_cflags,
98
+ harness_cxxflags=parameters.harness_cxxflags,
99
+ ),
100
+ )
101
+ return write_executable(workdir / "compile_harnesses.sh", build_harnesses_script())
102
+
103
+
104
+ def write_project_yaml(output_path: Path, analysis: AnalysisResult) -> Path:
105
+ """Write project.yaml — depends only on analysis, so it never needs rewriting."""
106
+ path = output_path / "project.yaml"
107
+ path.write_text(
108
+ f"homepage: {analysis.clone_url}\n"
109
+ f"language: {analysis.language.value}\n"
110
+ "sanitizers:\n"
111
+ " - address\n"
112
+ " - undefined\n"
113
+ f"main_repo: {analysis.clone_url}\n"
114
+ )
115
+ return path
116
+
117
+
118
+ def write_dockerfile(
119
+ output_path: Path,
120
+ analysis: AnalysisResult,
121
+ *,
122
+ include_bear: bool,
123
+ base_image: str | None = None,
124
+ system_packages: list[str] | None = None,
125
+ ) -> Path:
126
+ """Write the OSS-Fuzz project Dockerfile.
127
+
128
+ include_bear=True produces the workspace's live copy, so the image the exploration probe
129
+ runs in always has bear for Make/Autotools compile_commands.json capture.
130
+ include_bear=False produces the shipped copy, which must not need a FuzzPrep-only tool.
131
+ """
132
+ path = output_path / "Dockerfile"
133
+ lines = [
134
+ f"FROM {base_image or DEFAULT_BASE_IMAGE}\n",
135
+ f"ENV FUZZING_LANGUAGE={analysis.language.value}\n",
136
+ ]
137
+
138
+ apt_packages: list[str] = []
139
+ if include_bear:
140
+ apt_packages.append("bear")
141
+ if analysis.autotools_setup in {
142
+ AutotoolsSetup.AUTOGEN,
143
+ AutotoolsSetup.BOOTSTRAP,
144
+ AutotoolsSetup.AUTORECONF,
145
+ }:
146
+ apt_packages.extend(_AUTOTOOLS_PACKAGES)
147
+ apt_packages.extend(system_packages or [])
148
+ if apt_packages:
149
+ lines.append(f"{APT_INSTALL_PREFIX} {' '.join(dict.fromkeys(apt_packages))}\n")
150
+
151
+ lines.append(f"RUN git clone --recursive {analysis.clone_url} $SRC/src\n")
152
+ if analysis.repo_ref is not None:
153
+ lines.append(f"RUN git -C $SRC/src checkout {analysis.repo_ref}\n")
154
+ lines += [
155
+ f"COPY {HARNESS_SOURCE_DIR} $SRC/{HARNESS_SOURCE_DIR}\n",
156
+ "COPY build.sh build_library.sh compile_harness.sh compile_harnesses.sh $SRC/\n",
157
+ "WORKDIR $SRC/src\n",
158
+ ]
159
+ path.write_text("".join(lines))
160
+ return path
161
+
162
+
163
+ def inject_apt_packages(output_path: Path, packages: list[str]) -> Path:
164
+ """Merge newly-discovered apt packages into an existing Dockerfile, in place.
165
+
166
+ Merges rather than re-renders, so agent edits survive: this file is written before the
167
+ harness phase can know what else is needed, and generation only ever copies it.
168
+ """
169
+ path = output_path / "Dockerfile"
170
+ if not packages:
171
+ return path
172
+ lines = path.read_text().splitlines(keepends=True)
173
+ for i, line in enumerate(lines):
174
+ if line.startswith(APT_INSTALL_PREFIX):
175
+ existing = line[len(APT_INSTALL_PREFIX) :].split()
176
+ merged = list(dict.fromkeys(existing + packages))
177
+ lines[i] = f"{APT_INSTALL_PREFIX} {' '.join(merged)}\n"
178
+ break
179
+ else:
180
+ insert_at = next(
181
+ (i + 1 for i, line in enumerate(lines) if line.startswith("ENV FUZZING_LANGUAGE=")),
182
+ len(lines),
183
+ )
184
+ lines.insert(insert_at, f"{APT_INSTALL_PREFIX} {' '.join(dict.fromkeys(packages))}\n")
185
+ path.write_text("".join(lines))
186
+ return path
187
+
188
+
189
+ def write_build_sh(output_path: Path) -> Path:
190
+ """Write build.sh — the library build then harness compilation, with a marker per stage.
191
+
192
+ OSS-Fuzz's `compile` runs it, check_build.sh runs it and then asserts, and a host user can
193
+ run it directly.
194
+ """
195
+ return write_executable(output_path / "build.sh", _BUILD_SH)
196
+
197
+
198
+ def strip_bear_dependency(dockerfile_content: str) -> str:
199
+ """Drop the "bear" apt package, which only the workspace image needs.
200
+
201
+ Splits the package list into tokens rather than replacing a fixed string, since "bear" is
202
+ not always followed by a space — it may be last in the list.
203
+ """
204
+ lines = []
205
+ for line in dockerfile_content.splitlines(keepends=True):
206
+ if not line.startswith(APT_INSTALL_PREFIX):
207
+ lines.append(line)
208
+ continue
209
+ packages = [pkg for pkg in line[len(APT_INSTALL_PREFIX) :].split() if pkg != "bear"]
210
+ if packages:
211
+ lines.append(f"{APT_INSTALL_PREFIX} {' '.join(packages)}\n")
212
+ # else: bear was the only package — drop the now-empty install line entirely.
213
+ return "".join(lines)
214
+
215
+
216
+ def find_compile_commands(workdir: Path) -> Path | None:
217
+ """The compile_commands.json the gate's build left in workdir, or None if it left none.
218
+
219
+ Read from the layout rather than threaded through a result object, because threading it is
220
+ what lost it: the repair agents return a fresh result and had no field for it, so an
221
+ agent-fixed build published none even though the gate had just written one.
222
+
223
+ Whichever of these exists describes the build that actually passed. On the agent lane the
224
+ gate wipes `install` and `build` and rebuilds from nothing, so the capture is the gate's;
225
+ on the deterministic lane the gate skips the library build and the capture is the cold
226
+ build explore() ran, which is the same build the gate then accepted. `build/` comes first:
227
+ when `bear` is installed both exist for a CMake project, and CMake's own export does not
228
+ carry the compiler-probe entries (`CompilerIdC`, `TryCompile`) that bear observes.
229
+ """
230
+ for candidate in (
231
+ workdir / "build" / "compile_commands.json",
232
+ workdir / "compile_commands.json",
233
+ ):
234
+ if candidate.is_file():
235
+ return candidate
236
+ return None
237
+
238
+
239
+ __all__ = [
240
+ "APT_INSTALL_PREFIX",
241
+ "DEFAULT_BASE_IMAGE",
242
+ "find_compile_commands",
243
+ "inject_apt_packages",
244
+ "materialize",
245
+ "strip_bear_dependency",
246
+ "write_build_sh",
247
+ "write_dockerfile",
248
+ "write_harness_scripts",
249
+ "write_project_yaml",
250
+ ]
@@ -0,0 +1,255 @@
1
+ Metadata-Version: 2.4
2
+ Name: fuzzprep
3
+ Version: 0.1.0
4
+ Summary: Prepare software libraries for reproducible OSS-Fuzz project generation.
5
+ Author: Trail of Bits
6
+ Author-email: Trail of Bits <opensource@trailofbits.com>
7
+ License-Expression: Apache-2.0
8
+ License-File: LICENSE
9
+ License-File: THIRD_PARTY_NOTICES.md
10
+ Requires-Dist: pyyaml>=6.0
11
+ Requires-Python: >=3.13
12
+ Project-URL: Homepage, https://pypi.org/project/fuzzprep/
13
+ Project-URL: Source, https://github.com/trailofbits/fuzzprep
14
+ Project-URL: Issues, https://github.com/trailofbits/fuzzprep/issues
15
+ Description-Content-Type: text/markdown
16
+
17
+ # FuzzPrep
18
+
19
+ FuzzPrep is a CLI that takes the manual effort out of building C/C++ libraries for fuzzing
20
+ while aiming to minimize LLM token cost. It detects the build system, builds the library,
21
+ probes harness compilation to find linker dependencies, and writes artifacts that build and
22
+ link the library against a harness.
23
+
24
+ ## Prerequisites
25
+
26
+ ### What FuzzPrep needs
27
+
28
+ - Python 3.13 and [`uv`](https://docs.astral.sh/uv/).
29
+ - `git`, to clone the target repository.
30
+ - `clang` and `clang++`, the default compilers. `--cc` and `--cxx` select others.
31
+ - libFuzzer's runtime, which `clang` links for the default `-fsanitize=fuzzer` harness flags.
32
+ It is a separate package: `libclang-rt-dev` on Debian and Ubuntu, `compiler-rt` elsewhere.
33
+ A plain `apt install clang` pulls it in as a recommended package, but an install that uses
34
+ `--no-install-recommends` does not, so name it.
35
+
36
+ ```bash
37
+ sudo apt update
38
+ sudo apt install -y git clang libclang-rt-dev
39
+ ```
40
+
41
+ ### Common library build dependencies
42
+
43
+ A target brings its own build dependencies: the build system it uses, and the `-dev` packages
44
+ it links against. FuzzPrep reports the packages a failed run is missing. The below script also installs a set that covers many targets — the four supported build systems, the usual codegen and
45
+ archive utilities, and the libraries FuzzPrep knows how to identify from error traces:
46
+
47
+ ```bash
48
+ ./scripts/install_common_deps.sh
49
+ ```
50
+
51
+ The list is not exhaustive. When a build fails on a dependency the script does not cover,
52
+ install that dependency and run again.
53
+
54
+ ### Optional
55
+
56
+ - Docker, for `--environment oss-fuzz`.
57
+ - The `claude` or `codex` CLI, for agent repair. It is on by default; `--no-agents` turns it
58
+ off and no CLI is then needed.
59
+ - [`bear`](https://github.com/rizsotto/Bear), for Make and Autotools targets built with
60
+ `--environment local`. It captures `compile_commands.json`, which `extract-features` and
61
+ `generate-yaml` read.
62
+ - `cmake`, `llvm-dev`, `libclang-20`, and `libclang-dev`, which `extract-features` builds its Clang
63
+ LibTooling parser against. With more than one LLVM installed, point `CMAKE_PREFIX_PATH` at
64
+ the tree the `clang` on `PATH` belongs to.
65
+
66
+ The apt packages among these:
67
+
68
+ ```bash
69
+ sudo apt install -y bear cmake llvm-dev libclang-dev libclang-20
70
+ ```
71
+
72
+ ## Install
73
+
74
+ ```bash
75
+ uv sync
76
+ ```
77
+
78
+ ## Quickstart
79
+
80
+ >**Best practice:** Run FuzzPrep in a container or disposable VM. FuzzPrep compiles and executes
81
+ > arbitrary build-system logic from the target library. Its agentic workflow may also write and
82
+ > execute build scripts, so it should be run in an isolated environment.
83
+
84
+ From a local checkout after `uv sync`:
85
+
86
+ ```bash
87
+ # Clones the repository, builds it, verifies it, and writes `output/zlib/`.
88
+ uv run fuzzprep generate https://github.com/madler/zlib.git
89
+ ```
90
+
91
+ To run FuzzPrep without cloning this repository:
92
+
93
+ ```bash
94
+ uvx fuzzprep generate https://github.com/madler/zlib.git
95
+ ```
96
+
97
+ Other useful flags include:
98
+
99
+ ```bash
100
+ # Verify in the OSS-Fuzz Docker environment instead of on the host
101
+ uv run fuzzprep generate <REPO_URL> --environment oss-fuzz
102
+
103
+ # Turn off agent repair: a failed build then simply fails the run
104
+ uv run fuzzprep generate <REPO_URL> --no-agents
105
+
106
+ # Pass build-system configure options (repeat for more than one)
107
+ uv run fuzzprep generate <REPO_URL> --library-configure-arg=-DCARES_STATIC=ON
108
+
109
+ # Skip the from-scratch rebuild that validates an agent's repair, for a faster run
110
+ uv run fuzzprep generate <REPO_URL> --bypass-scratch-validation
111
+
112
+ # Use distinct library and final-harness instrumentation defaults
113
+ uv run fuzzprep generate <REPO_URL> --environment local \
114
+ --cc clang --cxx clang++ \
115
+ --library-cflags='-fsanitize=fuzzer-no-link,address' \
116
+ --library-cxxflags='-fsanitize=fuzzer-no-link,address' \
117
+ --harness-cflags='-fsanitize=fuzzer,address' \
118
+ --harness-cxxflags='-fsanitize=fuzzer,address'
119
+ ```
120
+
121
+ Agent repair is on by default and calls a paid network service. `--agent claude` (the
122
+ default) or `--agent codex` selects the backend; `--no-agents` turns it off.
123
+
124
+ See `uv run fuzzprep generate --help` for the full set of options (custom output
125
+ location, pinning a branch/tag/commit, a different base image, etc).
126
+
127
+ ### Adaptable builds
128
+
129
+ The generated build scripts let you supply your own toolchain and flags:
130
+
131
+ ```bash
132
+ CC=afl-clang-fast CXX=afl-clang-fast++ \
133
+ CFLAGS=-fsanitize=address CXXFLAGS=-fsanitize=address \
134
+ ./build_library.sh
135
+ ```
136
+
137
+ ### When a run fails
138
+
139
+ FuzzPrep keeps its working state in `.fuzzprep/<project>/`: the workspace it built in,
140
+ `logs/` with the raw output of each phase, and `stats.json`. A failed run writes no output
141
+ directory, but the library build artifacts stay in `.fuzzprep/<project>/install/` if you want
142
+ to debug the link line there. Add `--log-level debug` for more detail, or `--quiet` to hide
143
+ the raw subprocess output while a phase runs.
144
+
145
+ ## What it does
146
+
147
+ 1. Detects the build system: CMake, Meson, Autotools, or Makefile.
148
+ 2. Builds the library with a deterministic script. If that build fails, an agent repairs it.
149
+ 3. Probes harness compilation to find transitive linker dependencies. If the probe fails,
150
+ an agent repairs it.
151
+ 4. Writes the output directory `<output>/<project>/`.
152
+
153
+ ## Output
154
+
155
+ The output directory provides a reproducible OSS-Fuzz project and a standalone host build
156
+ tree. `docker build .` works, and so does `./setup.sh && ./build_library.sh`.
157
+
158
+ ```
159
+ output/<project>/
160
+ ├── Dockerfile # OSS-Fuzz project files
161
+ ├── project.yaml # OSS-Fuzz project metadata
162
+ ├── .dockerignore
163
+ ├── setup.sh # Script for repo clone + apt dependencies
164
+ ├── build.sh # Builds the library and compiles the provided harness
165
+ ├── build_library.sh # build and install the library into install/
166
+ ├── compile_harness.sh # compile and link one harness source
167
+ ├── compile_harnesses.sh # compile every source in harness_source/ into out/
168
+ ├── harness_source/ # source code of all harnesses
169
+ ├── install/ # the library this run built
170
+ ├── compile_commands.json # captured compile commands
171
+ ├── stats.json # what this run did: durations, agent use, status
172
+ └── README.md # what this run verified, and how to run it
173
+ ```
174
+
175
+ `harness_source/` starts with a stub — an `LLVMFuzzerTestOneInput` with a
176
+ `// TODO: Add fuzzing logic` body. FuzzPrep proves the harness *compiles and links* against
177
+ the library; writing the fuzzing logic is yours.
178
+
179
+ ## Environments
180
+
181
+ `--environment` selects where this run builds and verifies. It does not change what is
182
+ generated: the output directory always holds both setups. The generated `README.md` records
183
+ which of the two this run exercised.
184
+
185
+ - `local` — build and verify on the host.
186
+ - `oss-fuzz` — build and verify in an OSS-Fuzz compatible Docker container, then prove the
187
+ generated Dockerfile builds from scratch.
188
+
189
+ Neither environment isolates the target's build from your machine well enough to trust it.
190
+ Run both inside a VM or an isolated machine.
191
+
192
+ ## Other commands
193
+
194
+ `generate` produces a `compile_commands.json` file that two follow-on commands consume, to
195
+ extract the library's API surface (`extract-features`) and to produce an OSS-Fuzz-Gen
196
+ compatible YAML input (`generate-yaml`).
197
+
198
+ ```bash
199
+ uv run fuzzprep extract-features <BUILD_PATH> # -> features.json (run this first)
200
+ uv run fuzzprep generate-yaml <BUILD_PATH> # -> <project>.yaml
201
+ ```
202
+
203
+ `extract-features` runs a Clang LibTooling-based parser over every header and source file in
204
+ `compile_commands.json`. It writes `<BUILD_PATH>/features.json`, a structured inventory of
205
+ the library's C/C++ declarations:
206
+
207
+ - `functions` — name, return type, parameters, full signature, declaring header, and
208
+ whether it is public API (declared in a header, not `static`)
209
+ - `typedefs` — name, underlying type, declaring header
210
+ - `macros` — name, object- or function-like, parameters (if function-like), value,
211
+ declaring header
212
+ - `enums` — name (if any), enumerators with their values, declaring header
213
+ - `records` — structs and unions: name (if any), `kind`, fields, declaring header
214
+ - `warnings` — non-fatal problems found during the parse
215
+
216
+ `generate-yaml` reads `features.json` and keeps only the public functions. To get
217
+ finer-grained output, name one or more headers and it keeps only the functions those headers
218
+ declare:
219
+
220
+ ```bash
221
+ uv run fuzzprep generate-yaml <BUILD_PATH> zlib.h zconf.h
222
+ ```
223
+
224
+ Run `uv run fuzzprep --help` for details.
225
+
226
+ ## Security
227
+
228
+ FuzzPrep clones and builds arbitrary third-party repositories, which runs their build systems
229
+ on your machine, and it hands a repair agent write access to the run's workspace.
230
+
231
+ Run it in a VM or on a dedicated machine you can wipe, whatever `--environment` you pick. A
232
+ container shares the host kernel and is not a boundary that holds against code written to
233
+ break out of one, so `--environment oss-fuzz` reduces the blast radius of an ordinary build
234
+ but does not contain a hostile one. `--no-agents` turns agent repair off.
235
+
236
+ [SECURITY.md](SECURITY.md) has the full threat model and tells you how to report a
237
+ vulnerability.
238
+
239
+ ## Contributing
240
+
241
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the local setup, the checks a pull request must
242
+ pass, and what each pytest marker needs. Participation is governed by the
243
+ [Code of Conduct](CODE_OF_CONDUCT.md).
244
+
245
+ ## License
246
+
247
+ FuzzPrep is licensed under [Apache-2.0](LICENSE).
248
+
249
+ The `feature_extractor` tool that `extract-features` builds links cJSON and the LLVM/Clang
250
+ libraries. [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) records their licenses and the
251
+ notices that apply if you redistribute that binary.
252
+
253
+ Some files under `tests/real_harnesses/` come from upstream projects and keep their own
254
+ licenses; [that directory's README](tests/real_harnesses/README.md) records the provenance of
255
+ each one.
@@ -0,0 +1,56 @@
1
+ fuzzprep/__init__.py,sha256=tr2-zP7nAwYvPIwHWMSf1BmGnXbB-5N7mN_ONxhPZAw,49
2
+ fuzzprep/__main__.py,sha256=Vli4O9JijdrIzCVsmyfYeanw_oWjJ62kVkA5Q4UV0Gc,87
3
+ fuzzprep/agents/harness_builder/SKILL.md,sha256=04sHLIhZ93zClkHSntUFhc74tLMAPlKLCNnvDyVGfrg,9090
4
+ fuzzprep/agents/library_builder/SKILL.md,sha256=HncRQbGd0fKbbDrUwMsC46-oX0EHBxBddHHjx2KXqlc,8423
5
+ fuzzprep/agents/scripts/check_build.sh,sha256=zHu8EkuHVPSG8RR6eH9lVghXGuKWHmigX_rzE_H3rMg,3463
6
+ fuzzprep/agents/scripts/check_build_in_container.sh,sha256=PxX-eb1OIdJIK_lz8BEt3bDxCwN04ByBG-rtbvQNn1A,2972
7
+ fuzzprep/agents/scripts/check_dockerfile_from_scratch.sh,sha256=O-qQWAxYXRr-_JxM-WGNpq604TSgWKBBLYtmDEVA4NE,1109
8
+ fuzzprep/cli.py,sha256=EfA7m0LRI_aeayqLFOP4OZ3EPKcRzDNDEUw7F6ucwEo,41069
9
+ fuzzprep/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ fuzzprep/core/agent_stream.py,sha256=0rdKNFBUN-3I7cDs_ZR3ltrghnX9_X23mG-bID8yuts,10849
11
+ fuzzprep/core/files.py,sha256=VjcTp-AIteIH4Cl5j_E4KA3qF4fGa29y66zT2Ft0k_A,1124
12
+ fuzzprep/core/paths.py,sha256=Y6ilp0uQtBwIXNrAvODrzZo9gcEcu_GUvnC3Nam6N-E,792
13
+ fuzzprep/core/reporting.py,sha256=YHeN8qINnsCaQvcCY1f462NH6QLiE2fMUGyLk3CDC44,7260
14
+ fuzzprep/core/repos.py,sha256=lNUMKTT0OIstDMYCbHu9Am2rrTM0CcNURRkUHGFLZqE,8950
15
+ fuzzprep/core/resources.py,sha256=Io3tqGZVlf2bAQ5cVY2dK4oY5KhFBRqOKIMrooE58lo,1643
16
+ fuzzprep/core/subprocesses.py,sha256=1MankZ_OZy4ddYlN_SS5m2Xd7n8bLP2D0ytxzEqtxLU,6536
17
+ fuzzprep/feature_extractor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ fuzzprep/feature_extractor/benchmark_yaml.py,sha256=qCQbVEUBWtlXUVZ_4feWkZlj3KHZoTi-sTF-6KNSEEU,2906
19
+ fuzzprep/feature_extractor/extraction.py,sha256=tQYNCUxfnLVOwEmb6xR3YhQwsSOw_0rKAf4hTiZ07ps,6317
20
+ fuzzprep/feature_extractor/models.py,sha256=NtxeAICy_c58myoA2mWeXcIygbX_t8sOSAtqj3uQ9fc,1740
21
+ fuzzprep/feature_extractor/native/.clang-format,sha256=Gy1Z5l97bDY7urRaehBX0PShvjrbMHuDIMCVGsVyEGk,19
22
+ fuzzprep/feature_extractor/native/CMakeLists.txt,sha256=m_0a0a_VRxx6uhaTmRAaPscVYQfTm7owZIgwdUp1TMg,2798
23
+ fuzzprep/feature_extractor/native/include/feature_extractor.hpp,sha256=pKTsFLdYnUl95iKD7daijOWD0RIBkF7YGmZnNB4QM00,4062
24
+ fuzzprep/feature_extractor/native/src/extraction_action.cpp,sha256=ULcF_50PAZo6c0xP7qwuK21RyFf1V2PRAsYNjFX0fYY,9293
25
+ fuzzprep/feature_extractor/native/src/json_writer.cpp,sha256=zU9Lv7982AMkiRUXms0F0s6-BrtbQnM3GYPC16yl9iI,5391
26
+ fuzzprep/feature_extractor/native/src/macro_callbacks.cpp,sha256=qjhx4Bnuei357FzRvECo8RgZARL86lomkbQgbAl1Qpc,2384
27
+ fuzzprep/feature_extractor/native/src/main.cpp,sha256=Doflnc45NtB8qjp4vRBx_b3wHU2aP4Z3m4inguemizs,4680
28
+ fuzzprep/feature_extractor/native_build.py,sha256=R20UPQJ_eyZ3su5k51RAaotGa9DrqlZlkuds8I5z03g,4077
29
+ fuzzprep/library_builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ fuzzprep/library_builder/agents.py,sha256=2Ap_8076q9QkzgFSW7Fs0tkr0opErNXc9ZJcsvcuDrg,20009
31
+ fuzzprep/library_builder/analysis.py,sha256=4D7pavJbSdb7BZb9DZnHJAk_kFM47ymce5IJuvSq9sE,5464
32
+ fuzzprep/library_builder/build_parameters.py,sha256=TWeo1GQGbPTiLzI5djAAFR9ONjNkUuxXbkSd3bS64X8,6116
33
+ fuzzprep/library_builder/dependency_resolution.py,sha256=7aQh7ntDCB2NcHf7P18K5zfBPYUxOeGPYSOIzvOyC70,4988
34
+ fuzzprep/library_builder/environments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ fuzzprep/library_builder/environments/base.py,sha256=RrK7bJ8dOF5zIZiFE50qewJXTyMlg4Hq635pTCAfkXU,3409
36
+ fuzzprep/library_builder/environments/gate.py,sha256=h5TU2piV5fUtRyMTy2t6g2q1zBMFgpDe6Qyi3NDnJz0,4194
37
+ fuzzprep/library_builder/environments/local.py,sha256=LOLQwIsR827OK_hpYY-ogBrhYpS7TwtvX_f0vYioW70,9073
38
+ fuzzprep/library_builder/environments/oss_fuzz.py,sha256=35H9I-lIAMzPrgVp7rHOfrcvUQK2aSjTFE7inD44QXI,20410
39
+ fuzzprep/library_builder/environments/verification.py,sha256=obRXSMvM_3QcOomTh6LrAcn0MrwMJvn3YROzsEwHvy8,4858
40
+ fuzzprep/library_builder/exploration.py,sha256=vLQa3aTfko9WaC1tHwA6gQlW0Pz7qh3VT82qHw1UlzQ,8195
41
+ fuzzprep/library_builder/generation.py,sha256=VwL6sVRKPT95Ocp6NObgicvvjohT8XW8kTDVaOVpEWw,13537
42
+ fuzzprep/library_builder/harness_explorer.py,sha256=c24Ly5Ugnb3KVDBPJYdYQnknuZdw9YK1h5du0qIPa6M,9851
43
+ fuzzprep/library_builder/models.py,sha256=SYWHsnVykYZwN0X7mfiHqG3bxUO2YCEeqsKzy1c3AZ4,5745
44
+ fuzzprep/library_builder/package_names.json,sha256=TBKO6NNLY5g5puB-7VIuM0yd2Dhu3OV9Sla5Nfvvg78,984
45
+ fuzzprep/library_builder/package_names.py,sha256=BbOgBof8vgoXOgeUg5Re5K8j8S_E3t3XHZgQmmUcYIU,1153
46
+ fuzzprep/library_builder/scripts.py,sha256=YtJ7tuXU5-gxoHx72xfi4k4I-iPdCoAtHPg6HisiFqc,15264
47
+ fuzzprep/library_builder/stats.py,sha256=nOtpo7bVycr_8PMYD6-ko9cdBtsXsy1k9mWXAoKZ0F8,3817
48
+ fuzzprep/library_builder/symbol_patterns.json,sha256=QE9GVcTmCzl16vm0f8pB8QggEywwFhxqVKLPx5zo6o4,2011
49
+ fuzzprep/library_builder/timeouts.py,sha256=8DlI6TJyPFiRKiFWUinxIK_H4DV0JBqERgz373FFids,566
50
+ fuzzprep/library_builder/workspace.py,sha256=sIUi4_sz9w_sMOk1IN8Z1L6Vj9Dltll7z-l8PbuA4CE,9758
51
+ fuzzprep-0.1.0.dist-info/licenses/LICENSE,sha256=TXPiF794qJbbb6wtrr2WqSpDFm3rAvHqkqBIhmMYADE,11377
52
+ fuzzprep-0.1.0.dist-info/licenses/THIRD_PARTY_NOTICES.md,sha256=HrCPPPGcVFjX7l69JZEH34oAqqyal8lb4pNpkbXbTks,2515
53
+ fuzzprep-0.1.0.dist-info/WHEEL,sha256=nQ0eT7mepDP-DkLACRDiCUi7cAIJyLg4OevuC4KpLLY,80
54
+ fuzzprep-0.1.0.dist-info/entry_points.txt,sha256=ujRytgUod2sT08KmZe3BIGBxfeRouaq5NKHWYmP82A0,53
55
+ fuzzprep-0.1.0.dist-info/METADATA,sha256=jctV5zz-4LjrFUN2paL47wI3QDEnnWW-R4VZOhheon0,10412
56
+ fuzzprep-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.12.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ fuzzprep = fuzzprep.__main__:main
3
+