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.
- fuzzprep/__init__.py +3 -0
- fuzzprep/__main__.py +4 -0
- fuzzprep/agents/harness_builder/SKILL.md +156 -0
- fuzzprep/agents/library_builder/SKILL.md +147 -0
- fuzzprep/agents/scripts/check_build.sh +87 -0
- fuzzprep/agents/scripts/check_build_in_container.sh +73 -0
- fuzzprep/agents/scripts/check_dockerfile_from_scratch.sh +33 -0
- fuzzprep/cli.py +1109 -0
- fuzzprep/core/__init__.py +0 -0
- fuzzprep/core/agent_stream.py +304 -0
- fuzzprep/core/files.py +35 -0
- fuzzprep/core/paths.py +25 -0
- fuzzprep/core/reporting.py +218 -0
- fuzzprep/core/repos.py +217 -0
- fuzzprep/core/resources.py +41 -0
- fuzzprep/core/subprocesses.py +197 -0
- fuzzprep/feature_extractor/__init__.py +0 -0
- fuzzprep/feature_extractor/benchmark_yaml.py +92 -0
- fuzzprep/feature_extractor/extraction.py +184 -0
- fuzzprep/feature_extractor/models.py +96 -0
- fuzzprep/feature_extractor/native/.clang-format +1 -0
- fuzzprep/feature_extractor/native/CMakeLists.txt +90 -0
- fuzzprep/feature_extractor/native/include/feature_extractor.hpp +136 -0
- fuzzprep/feature_extractor/native/src/extraction_action.cpp +294 -0
- fuzzprep/feature_extractor/native/src/json_writer.cpp +154 -0
- fuzzprep/feature_extractor/native/src/macro_callbacks.cpp +75 -0
- fuzzprep/feature_extractor/native/src/main.cpp +130 -0
- fuzzprep/feature_extractor/native_build.py +99 -0
- fuzzprep/library_builder/__init__.py +0 -0
- fuzzprep/library_builder/agents.py +472 -0
- fuzzprep/library_builder/analysis.py +145 -0
- fuzzprep/library_builder/build_parameters.py +158 -0
- fuzzprep/library_builder/dependency_resolution.py +139 -0
- fuzzprep/library_builder/environments/__init__.py +0 -0
- fuzzprep/library_builder/environments/base.py +89 -0
- fuzzprep/library_builder/environments/gate.py +96 -0
- fuzzprep/library_builder/environments/local.py +205 -0
- fuzzprep/library_builder/environments/oss_fuzz.py +485 -0
- fuzzprep/library_builder/environments/verification.py +125 -0
- fuzzprep/library_builder/exploration.py +217 -0
- fuzzprep/library_builder/generation.py +325 -0
- fuzzprep/library_builder/harness_explorer.py +257 -0
- fuzzprep/library_builder/models.py +169 -0
- fuzzprep/library_builder/package_names.json +33 -0
- fuzzprep/library_builder/package_names.py +40 -0
- fuzzprep/library_builder/scripts.py +389 -0
- fuzzprep/library_builder/stats.py +102 -0
- fuzzprep/library_builder/symbol_patterns.json +65 -0
- fuzzprep/library_builder/timeouts.py +14 -0
- fuzzprep/library_builder/workspace.py +250 -0
- fuzzprep-0.1.0.dist-info/METADATA +255 -0
- fuzzprep-0.1.0.dist-info/RECORD +56 -0
- fuzzprep-0.1.0.dist-info/WHEEL +4 -0
- fuzzprep-0.1.0.dist-info/entry_points.txt +3 -0
- fuzzprep-0.1.0.dist-info/licenses/LICENSE +202 -0
- fuzzprep-0.1.0.dist-info/licenses/THIRD_PARTY_NOTICES.md +52 -0
fuzzprep/__init__.py
ADDED
fuzzprep/__main__.py
ADDED
|
@@ -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"
|