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
fuzzprep/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ __version__ = "0.1.0"
2
+
3
+ __all__ = ["__version__"]
fuzzprep/__main__.py ADDED
@@ -0,0 +1,4 @@
1
+ from fuzzprep.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())
@@ -0,0 +1,156 @@
1
+ You are helping debug and fix a failed harness compilation/link probe for a C/C++ library.
2
+
3
+ Your goal: make compile_harness.sh succeed so that a supplied harness compiles and links
4
+ against the library's static artifacts, producing a binary in out/.
5
+
6
+ ## What you have
7
+
8
+ The failure context will be appended below. It includes:
9
+ - The install directory containing static libraries (install/lib/*.a) and headers (install/include/)
10
+ - The work directory containing compile_harness.sh and harness_source/
11
+ - The static libraries already discovered
12
+ - Any link flags already auto-resolved from known symbol patterns
13
+ - Any missing system libraries already reported by the linker
14
+ - The complete stderr from the failed compile/link attempt (last 200 lines)
15
+
16
+ workdir is not a scratch directory — it is the real project directory that generation
17
+ copies its final output from (for oss-fuzz, it's the same directory that becomes the
18
+ shipped project). Edits you make here to compile_harness.sh, a Dockerfile, or other
19
+ files persist into that output.
20
+
21
+ ## Reproducibility
22
+
23
+ The verification command — and every future rebuild of this project, on any machine,
24
+ months from now — only ever sees the files saved in workdir plus a fresh `git clone` of
25
+ the library's source. Two rules follow from that:
26
+
27
+ - **Persist every fix to disk, and only to disk.** Nothing outside what's saved in
28
+ `compile_harness.sh` (or a Dockerfile/patch file it invokes) survives to the next
29
+ run — not a command typed directly in this shell, not an exported env var, not a
30
+ file edited by hand outside what the script itself does. The script must succeed
31
+ standalone against a fresh `install/`, with no leftover state from this or any prior
32
+ session. If a fix needs an env var, a package, or a symlink, encode it into
33
+ compile_harness.sh (or the Dockerfile) so a fresh checkout reproduces it identically.
34
+ - **Hand-edits to the source tree do not persist.** Both the local `setup.sh` and the
35
+ shipped oss-fuzz `Dockerfile` re-clone the library from git at build time — the copy
36
+ of the source sitting in workdir right now is discarded the moment you exit. If a fix
37
+ genuinely requires changing a source file (e.g. a missing header the harness needs),
38
+ encode that change as a step compile_harness.sh performs itself — e.g. a `sed -i`
39
+ invocation, or `patch < "$SCRIPT_DIR/some.patch"` where the patch file lives next to
40
+ compile_harness.sh — not a one-off edit to the file in the source directory.
41
+
42
+ Also: use the script's own `$SCRIPT_DIR`/`$BUILD_PREFIX`/`$INSTALL_DIR` variables
43
+ (already defined near the top of compile_harness.sh) instead of baking in this
44
+ session's actual filesystem paths (e.g. `/home/user/.fuzzprep/...`) — those paths
45
+ won't exist on a different machine or in a fresh container.
46
+
47
+ ## What to do
48
+
49
+ 1. Read compile_harness.sh in the work directory to understand the link command that was
50
+ attempted (STATIC_LIBS array, EXTRA_LINK_FLAGS, compiler invocation).
51
+ 2. Read the linker/compiler errors in the failure context to identify unresolved symbols
52
+ or missing libraries.
53
+ 3. Diagnose the failure:
54
+ - Undefined symbols usually mean a transitive dependency's `-lXXX` flag is missing from
55
+ EXTRA_LINK_FLAGS, or static library link order matters for this linker.
56
+ - "library not found" / "cannot find -lXXX" errors mean a system library isn't
57
+ installed on this machine.
58
+ 4. Decide how to fix it, based on whether the library is resolvable on this machine:
59
+ - **If adding a `-lXXX` flag lets the build compile and link successfully right now**
60
+ (the library is already present on this machine, or an alternative like a static
61
+ archive already in install/lib, or a different link order resolves it): make the
62
+ fix yourself — edit EXTRA_LINK_FLAGS, include paths, or static library link order
63
+ directly in compile_harness.sh — and verify it. Still report the flag in
64
+ `missing_libs`/`missing_apt_packages` in `agent_report.json` (see below), even though
65
+ it already worked here — FuzzPrep needs the package name recorded for portability
66
+ to environments that don't already have it.
67
+ - **If the library isn't resolvable on this machine at all** (nothing to link
68
+ against; installing a system package is unavoidable): do not edit
69
+ EXTRA_LINK_FLAGS yourself, since you cannot verify a fix you cannot compile.
70
+ Instead, identify the bare library name and report it via `missing_libs` (see
71
+ below), determine the actual apt package name (see `agent_report.json` fields), and
72
+ say in your own reply text:
73
+ "ACTION REQUIRED: Missing system packages detected. Please review agent_report.json
74
+ and install the listed packages, then re-run this agent."
75
+ Write that line yourself — not through `echo` or any other command, and not only
76
+ inside a file. The caller reads the marker from your response text only.
77
+ Write `agent_report.json`, and do not proceed further.
78
+ 5. Once you've made a fix, run the verification command given in the failure context below
79
+ (not compile_harness.sh directly) to confirm it now succeeds in the selected target
80
+ environment and a binary appears in out/.
81
+
82
+ ## `agent_report.json`
83
+
84
+ Before exiting — on **every** outcome, success or stop-for-human-action — write
85
+ `agent_report.json` to the work directory (the directory containing compile_harness.sh)
86
+ with this shape:
87
+
88
+ ```json
89
+ {
90
+ "summary": "libfoo.a alone is missing zlib symbols; linked against the system zlib at /usr/lib/x86_64-linux-gnu instead of requesting a new package.",
91
+ "missing_libs": [],
92
+ "missing_apt_packages": [],
93
+ "extra_include_paths": ["./src"],
94
+ "extra_library_paths": ["./src/build"]
95
+ }
96
+ ```
97
+
98
+ - `summary` (string): plain-language description of what you diagnosed/did. Always
99
+ include this, on both success and failure. If uncertain of an exact package name,
100
+ say so here rather than asserting it confidently.
101
+ - `missing_libs` (array of strings): bare library name(s) — the part after `-l` — for
102
+ every new `-lXXX` flag you added to EXTRA_LINK_FLAGS, whether or not installing a
103
+ package was needed to make it work. Empty array if you added no new flags.
104
+ - `missing_apt_packages` (array of strings): Debian/Ubuntu `apt-get install` package
105
+ names that provide the libraries above (e.g. `"libldap2-dev"` for `-lldap`), reported
106
+ alongside every entry in `missing_libs` — including ones already present on this
107
+ machine, for portability to environments that aren't. Every name here reaches the
108
+ generated `setup.sh` and Dockerfile, so this is how the package gets installed wherever
109
+ the output is used.
110
+ - `extra_include_paths` (array of strings): relative paths, outside `install/include`,
111
+ that you added to the harness compile command's `-I` search path to make the fix work.
112
+ Empty array if none.
113
+ - `extra_library_paths` (array of strings): relative paths, outside `install/lib`, that
114
+ you added to the harness link command's `-L` search path to make the fix work (e.g. a
115
+ system library location). Empty array if none.
116
+
117
+ Omit fields you have nothing to report for — they default to empty/absent on the
118
+ reading side.
119
+
120
+ ## Stopping conditions
121
+
122
+ You cannot signal an outcome through your process exit code — the runner invokes you via
123
+ `claude --print`, which exits 0 whenever the CLI itself ran, no matter how you decided to
124
+ stop. The `ACTION REQUIRED` line and `agent_report.json` are the only signals the caller
125
+ reads, so a stop that needs human action is detected *only* if you write that exact
126
+ marker.
127
+
128
+ The caller scans your response text for the marker — not the command output or file
129
+ contents in your transcript. So the marker counts only when *you* write it, and quoting
130
+ it while explaining something (including quoting this document) does not accidentally
131
+ signal a stop.
132
+
133
+ **Success** — the verification command exits 0. Write `agent_report.json` first, then
134
+ give a short success summary.
135
+
136
+ **Blocked on human action** (a library that must be installed) — write the exact
137
+ `ACTION REQUIRED:` line from step 4 and write `agent_report.json` with the package names.
138
+
139
+ **Unresolvable failure** — if the verification command still fails after your fix
140
+ attempt, or if you cannot determine a fix, stop immediately. Write `agent_report.json`
141
+ first, then report:
142
+ - What you diagnosed as the root cause
143
+ - What fix(es) you attempted (if any)
144
+ - The exact error from the build output
145
+
146
+ Do not retry indefinitely or attempt speculative fixes beyond what the evidence supports.
147
+ The caller detects this case by checking `out/` for a linked binary itself, so no marker is
148
+ needed — but put the diagnosis in `summary` so it reaches the failure report.
149
+
150
+ ## Important: non-interactive execution
151
+
152
+ This agent may be run non-interactively (e.g. via `claude --print`). In that
153
+ mode there is no user to respond to mid-run prompts. Never pause to ask the
154
+ user a question. If human input is required (e.g. to install packages), put all
155
+ necessary context in your reply, write any helper scripts to disk, and write the
156
+ `ACTION REQUIRED` marker yourself so the caller can detect and surface the situation.
@@ -0,0 +1,147 @@
1
+ You are helping debug and fix a failed C/C++ static library build.
2
+
3
+ Your goal: make the build_library.sh script succeed so that:
4
+ - static libraries (*.a) are installed to install/lib/
5
+ - headers are installed to install/include/
6
+
7
+ ## What you have
8
+
9
+ The build failure context will be appended below. It includes:
10
+ - The source directory path
11
+ - The detected build system
12
+ - The build command that was run
13
+ - The complete stdout/stderr from the failed build
14
+ - The expected install directory paths
15
+
16
+ workdir (the directory build_library.sh lives in) is not a scratch directory — it is the
17
+ real project directory that generation copies its final output from (for oss-fuzz, it's
18
+ the same directory that becomes the shipped project). Edits you make here to
19
+ build_library.sh, a Dockerfile, or other files persist into that output.
20
+
21
+ ## Reproducibility
22
+
23
+ The verification command — and every future rebuild of this project, on any machine,
24
+ months from now — only ever sees the files saved in workdir plus a fresh `git clone` of
25
+ the library's source. Two rules follow from that:
26
+
27
+ - **Persist every fix to disk, and only to disk.** Nothing outside what's saved in
28
+ `build_library.sh` (or a Dockerfile/patch file it invokes) survives to the next run —
29
+ not a command typed directly in this shell, not an exported env var, not a file
30
+ edited by hand outside what the script itself does. The script must succeed
31
+ standalone against a freshly cloned source tree, with no leftover state from this or
32
+ any prior attempt (a partially-built `build/` directory, a file created by hand). If
33
+ a fix needs an env var, a package, or a symlink, encode it into build_library.sh (or
34
+ the Dockerfile) so a fresh checkout reproduces it identically.
35
+ - **Hand-edits to the source tree do not persist.** Both the local `setup.sh` and the
36
+ shipped oss-fuzz `Dockerfile` re-clone the library from git at build time — the copy
37
+ of the source sitting in workdir right now is discarded the moment you exit. If a fix
38
+ genuinely requires changing a source file (a broken CMakeLists.txt, a workaround for a
39
+ compiler-version bug in a `.c` file), encode that change as a step build_library.sh
40
+ performs itself — e.g. a `sed -i` invocation, or `patch < "$SCRIPT_DIR/some.patch"`
41
+ where the patch file lives next to build_library.sh — not a one-off edit to the file
42
+ in the source directory.
43
+
44
+ Also: use the script's own `$SCRIPT_DIR`/`$BUILD_PREFIX`/`$INSTALL_DIR` variables
45
+ (already defined near the top of build_library.sh) instead of baking in this session's
46
+ actual filesystem paths (e.g. `/home/user/.fuzzprep/...`) — those paths won't exist
47
+ on a different machine or in a fresh container.
48
+
49
+ ## What to do
50
+
51
+ 1. Read build_library.sh in the work directory to understand what was attempted.
52
+ 2. Read the relevant build files (CMakeLists.txt, Makefile, configure.ac, meson.build, etc.).
53
+ 3. Diagnose the failure from the build output.
54
+ 4. Fix the problem: modify build_library.sh or other build files as needed.
55
+ Common fixes: wrong static library flags, configure options, disabling optional features.
56
+ 5. If missing system packages are the root cause, first try to disable the feature that
57
+ requires them via build flags (e.g. -DWITH_SSL=OFF, --disable-ssl, -Doption=disabled).
58
+ Prefer this over requesting package installation — optional features are not needed for
59
+ the core static library. Only escalate to package installation if the missing dependency
60
+ is critical to the library's core functionality (not just for optional functionality).
61
+ 6. If a required package cannot be avoided:
62
+ - Determine the actual installable Debian/Ubuntu (`apt-get`) package name from your own
63
+ knowledge. It is frequently different from the library name itself — e.g. OpenLDAP is
64
+ `libldap2-dev`. If uncertain of the exact package name, say so in `summary` rather
65
+ than asserting it confidently. Do not install anything yourself.
66
+ - Say clearly, in your own reply text, what is needed:
67
+ "ACTION REQUIRED: Missing system packages detected. Please review agent_report.json
68
+ and install the listed packages, then re-run this agent."
69
+ Write that line yourself — not through `echo` or any other command, and not only
70
+ inside a file. The caller reads the marker from your response text only.
71
+ - Write `agent_report.json` (see below), listing the package names, before exiting.
72
+ - Do not proceed further.
73
+ 7. Once any required packages are installed, run the verification command given in the
74
+ failure context below (not build_library.sh directly) to confirm the fix works in the
75
+ selected target environment. It is the authoritative check — it also compiles a stub
76
+ harness against your install/ output — so trust its exit code over eyeballing
77
+ install/lib and install/include yourself.
78
+
79
+ ## `agent_report.json`
80
+
81
+ Before exiting — on **every** outcome, success or stop-for-human-action — write
82
+ `agent_report.json` to the work directory (the directory containing build_library.sh,
83
+ **not** the source directory) with this shape:
84
+
85
+ ```json
86
+ {
87
+ "summary": "Disabled optional SSL support via -DWITH_SSL=OFF; libssl-dev was unavailable.",
88
+ "missing_apt_packages": ["libssl-dev", "libz-dev"],
89
+ "extra_include_paths": ["./src/"],
90
+ "extra_library_paths": ["./src/build"]
91
+ }
92
+ ```
93
+
94
+ - `summary` (string): plain-language description of what you diagnosed/did. Always
95
+ include this, on both success and failure.
96
+ - `missing_apt_packages` (array of strings): Debian/Ubuntu `apt-get install` package
97
+ names still needed (e.g. `"libssl-dev"`). Empty array if none. Correctness is of
98
+ utmost importance — do not list a package unless you are sure it exists. Every name here
99
+ reaches the generated `setup.sh` and Dockerfile, so this is how a package you needed gets
100
+ installed wherever the output is used.
101
+ - `extra_include_paths` (array of strings): relative paths, outside `install/include`,
102
+ that a downstream harness-compilation step should add to its `-I` search path if you
103
+ discovered the build needs one. Empty array if none.
104
+ - `extra_library_paths` (array of strings): relative paths, outside `install/lib`, that
105
+ a downstream harness-compilation step should add to its `-L` search path if you
106
+ discovered the build needs one. Empty array if none.
107
+
108
+ Omit fields you have nothing to report for a given field — they default to empty/absent
109
+ on the reading side. This is the only machine-readable report file you should write.
110
+
111
+ ## Stopping conditions
112
+
113
+ You cannot signal an outcome through your process exit code — the runner invokes you via
114
+ `claude --print`, which exits 0 whenever the CLI itself ran, no matter how you decided to
115
+ stop. The `ACTION REQUIRED` line and `agent_report.json` are the only signals the caller
116
+ reads, so a stop that needs human action is detected *only* if you write that exact
117
+ marker.
118
+
119
+ The caller scans your response text for the marker — not the command output or file
120
+ contents in your transcript. So the marker counts only when *you* write it, and quoting
121
+ it while explaining something (including quoting this document) does not accidentally
122
+ signal a stop.
123
+
124
+ **Success** — the verification command exits 0. Write `agent_report.json` first, then
125
+ give a short success summary.
126
+
127
+ **Blocked on human action** (a package that must be installed) — write the exact
128
+ `ACTION REQUIRED:` line from step 6 and write `agent_report.json` with the package names.
129
+
130
+ **Unresolvable failure** — if the verification command still fails after your fix
131
+ attempt, or if you cannot determine a fix, stop immediately. Write `agent_report.json`
132
+ first, then report:
133
+ - What you diagnosed as the root cause
134
+ - What fix(es) you attempted (if any)
135
+ - The exact error from the build output
136
+
137
+ Do not retry indefinitely or attempt speculative fixes beyond what the evidence supports.
138
+ The caller detects this case by checking `install/lib` and `install/include` itself, so no
139
+ marker is needed — but put the diagnosis in `summary` so it reaches the failure report.
140
+
141
+ ## Important: non-interactive execution
142
+
143
+ This agent may be run non-interactively (e.g. via `claude --print`). In that
144
+ mode there is no user to respond to mid-run prompts. Never pause to ask the
145
+ user a question. If human input is required (e.g. to install packages), put all
146
+ necessary context in your reply, write any helper scripts to disk, and write the
147
+ `ACTION REQUIRED` marker yourself so the caller can detect and surface the situation.
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env bash
2
+ # The single definition of "the build passed", for every environment.
3
+ #
4
+ # Runs the project's own build.sh (build_library.sh then compile_harnesses.sh) from nothing and
5
+ # asserts the artifacts that make the output worth shipping. The pipeline and every repair agent
6
+ # invoke this same script, so a fix an agent verifies is a fix the pipeline accepts.
7
+ #
8
+ # --keep-artifacts keeps install/ and build/, which skips the library rebuild. See the comment
9
+ # on the deletion below for who is allowed to pass it.
10
+ #
11
+ # Two fallbacks let one script text run unchanged on the host and in the OSS-Fuzz container:
12
+ # $OUT falls back to <workspace>/out, and the build is entered through `compile` wherever that
13
+ # exists and through build.sh otherwise.
14
+ set -euo pipefail
15
+
16
+ if [[ $# -lt 1 || $# -gt 2 ]]; then
17
+ echo "Usage: $0 <workspace> [--keep-artifacts]" >&2
18
+ exit 1
19
+ fi
20
+
21
+ workspace=$1
22
+ keep_artifacts=0
23
+ if [[ $# -eq 2 ]]; then
24
+ if [[ $2 != "--keep-artifacts" ]]; then
25
+ echo "Unknown option: $2 (expected --keep-artifacts)" >&2
26
+ exit 1
27
+ fi
28
+ keep_artifacts=1
29
+ fi
30
+
31
+ cd "$workspace"
32
+
33
+ OUT="${OUT:-$PWD/out}"
34
+ export OUT
35
+
36
+ # Deleting install/ and build/ is what makes this a from-scratch check. --keep-artifacts drops
37
+ # that, leaving build_library.sh's own skip-if-already-built guard to short-circuit the library
38
+ # build. Only a caller that already built the library from nothing may pass it -- the pipeline
39
+ # does so on the lane where explore() just did exactly that. A repair agent never passes it,
40
+ # because its whole job is changing the build, so its fix has to survive a real cold build.
41
+ if [[ $keep_artifacts -eq 0 ]]; then
42
+ rm -rf install build
43
+ fi
44
+ # $OUT is emptied rather than removed: check_build_in_container.sh bind-mounts the host's out/
45
+ # there, and a mountpoint cannot be unlinked from inside the container ("Device or resource
46
+ # busy"), which under set -e would fail the gate before the build even started.
47
+ #
48
+ # Emptied even under --keep-artifacts: compile_harnesses.sh always runs, so the $OUT assertion
49
+ # below stays a real check on this invocation rather than on a leftover binary.
50
+ mkdir -p "$OUT"
51
+ find "$OUT" -mindepth 1 -delete
52
+
53
+ # `compile` runs build.sh, but only after assembling what the base image half-provides:
54
+ # SANITIZER_FLAGS resolved into CFLAGS/CXXFLAGS, and LIB_FUZZING_ENGINE=-fsanitize=fuzzer in
55
+ # place of the deprecated archive path its ENV names. Running build.sh directly in that image
56
+ # links against an archive that does not exist yet, and working that around yields an
57
+ # uninstrumented target. A host has no `compile` and nothing to assemble.
58
+ build_command=(bash build.sh)
59
+ if command -v compile > /dev/null 2>&1; then
60
+ build_command=(compile)
61
+ fi
62
+
63
+ echo "=== build.sh ==="
64
+ if command -v bear > /dev/null 2>&1; then
65
+ # Captures compile_commands.json for Make/Autotools, which have no build-system equivalent.
66
+ # Harmless for the others, which emit their own.
67
+ bear -- "${build_command[@]}"
68
+ else
69
+ "${build_command[@]}"
70
+ fi
71
+
72
+ if ! compgen -G "install/lib/*.a" > /dev/null; then
73
+ echo "FAILED: no static libraries (*.a) found in install/lib" >&2
74
+ exit 1
75
+ fi
76
+
77
+ if [[ ! -d install/include ]] || [[ -z "$(ls -A install/include)" ]]; then
78
+ echo "FAILED: install/include is missing or empty" >&2
79
+ exit 1
80
+ fi
81
+
82
+ if [[ ! -d "$OUT" ]] || [[ -z "$(ls -A "$OUT")" ]]; then
83
+ echo "FAILED: $OUT is missing or empty — no harness binary was produced" >&2
84
+ exit 1
85
+ fi
86
+
87
+ echo "OK: build.sh succeeded and install/ plus $OUT are populated"
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env bash
2
+ # Run check_build.sh inside the workspace's own OSS-Fuzz image.
3
+ #
4
+ # Rebuilds the image from the workspace Dockerfile first, so an edit to it takes effect;
5
+ # Docker's layer cache makes that cheap when nothing changed. The workspace is then
6
+ # bind-mounted at /src, the path OSS-Fuzz tooling expects, so install/ and
7
+ # compile_commands.json land on the host for the next stage to use. The harness binaries need
8
+ # a mount of their own, since they go to the image's own $OUT=/out, outside /src — so
9
+ # <workspace>/out is bound there too, as OSS-Fuzz's helper.py does. Without it they would be
10
+ # discarded with the container, and a repair that linked something would look like one that
11
+ # only said so.
12
+ #
13
+ # This decides only where the gate runs. The assertions live in check_build.sh alone.
14
+ set -euo pipefail
15
+
16
+ if [[ $# -lt 2 || $# -gt 3 ]]; then
17
+ echo "Usage: $0 <workspace> <project_name> [--keep-artifacts]" >&2
18
+ exit 1
19
+ fi
20
+
21
+ workspace=$1
22
+ project_name=$2
23
+ # Passed straight through to check_build.sh inside the container, which validates it.
24
+ check_build_options=("${@:3}")
25
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
26
+ tag="fuzzprep-dev/${project_name}:latest"
27
+
28
+ cd "$workspace"
29
+
30
+ if ! docker build -t "$tag" .; then
31
+ echo "FAILED: docker build failed for $workspace" >&2
32
+ exit 1
33
+ fi
34
+
35
+ # Created before the mount so it belongs to the invoking user; Docker would otherwise create
36
+ # it root-owned, which the chown below cannot reach from the host side.
37
+ mkdir -p out
38
+
39
+ mounts=(
40
+ -v "$PWD:/src"
41
+ -v "$PWD/out:/out"
42
+ -v "$script_dir/check_build.sh:/usr/local/bin/check_build.sh:ro"
43
+ )
44
+
45
+ # The workspace mount covers /src whole, shadowing the source tree the image cloned there, so
46
+ # the container reads <workspace>/src from the host. An oss-fuzz run over a local path leaves
47
+ # that a symlink out of the workspace, which dangles in the container unless its target is
48
+ # mounted too — at its own path, which is what the symlink resolves to.
49
+ if [[ -L src ]]; then
50
+ source_target="$(readlink -f src)"
51
+ if [[ -n $source_target ]]; then
52
+ mounts+=(-v "$source_target:$source_target")
53
+ fi
54
+ fi
55
+
56
+ status=0
57
+ docker run --rm "${mounts[@]}" -w /src --entrypoint bash \
58
+ "$tag" /usr/local/bin/check_build.sh /src "${check_build_options[@]}" || status=$?
59
+
60
+ # The container runs as root, so install/, build/, and out/ come back root-owned and the next
61
+ # run cannot delete them. -h stops at the symlink above rather than following it into the
62
+ # source tree, which belongs to the user. /out is named explicitly rather than left to
63
+ # the walk of /src: it is the same host directory as /src/out, but naming it does not depend
64
+ # on chown descending into a nested bind mount.
65
+ docker run --rm "${mounts[@]}" --entrypoint chown \
66
+ "$tag" -Rh "$(id -u):$(id -g)" /src /out > /dev/null 2>&1 || true
67
+
68
+ if [[ $status -ne 0 ]]; then
69
+ echo "FAILED: check_build.sh did not succeed inside the container" >&2
70
+ exit 1
71
+ fi
72
+
73
+ echo "OK: check_build.sh succeeded inside the container"
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env bash
2
+ # Prove the shipped Dockerfile builds and compiles with nothing mounted.
3
+ #
4
+ # The gate (check_build_in_container.sh) mounts the workspace, which is what makes the artifacts
5
+ # reachable — but a mounted run can pass while the Dockerfile's own clone or apt layers are
6
+ # broken, since the mount supplies what the image failed to. This runs the real thing:
7
+ # `docker build`, then `compile`, no mounts, then a check for a harness binary in /out.
8
+ #
9
+ # Runs once, as the last step before generation, for an oss-fuzz target.
10
+ set -euo pipefail
11
+
12
+ if [[ $# -ne 2 ]]; then
13
+ echo "Usage: $0 <project_dir> <project_name>" >&2
14
+ exit 1
15
+ fi
16
+
17
+ project_dir=$1
18
+ project_name=$2
19
+ tag="${project_name}:fuzzprep-from-scratch"
20
+
21
+ cd "$project_dir"
22
+
23
+ if ! docker build -t "$tag" .; then
24
+ echo "FAILED: docker build failed for $project_dir" >&2
25
+ exit 1
26
+ fi
27
+
28
+ if ! docker run --rm --entrypoint bash "$tag" -c 'compile && test -n "$(ls -A /out)"'; then
29
+ echo "FAILED: compile (build.sh) or the /out check failed inside the container" >&2
30
+ exit 1
31
+ fi
32
+
33
+ echo "OK: from-scratch docker build and in-container compile succeeded"