Skip to content

fuzz: disable Zend's arena allocator under go-118-fuzz-build - #2604

Merged
dunglas merged 1 commit into
mainfrom
oss-fuzz/disable-zend-alloc-for-fuzzing
Aug 15, 2026
Merged

fuzz: disable Zend's arena allocator under go-118-fuzz-build#2604
dunglas merged 1 commit into
mainfrom
oss-fuzz/disable-zend-alloc-for-fuzzing

Conversation

@dunglas

@dunglas dunglas commented Aug 15, 2026

Copy link
Copy Markdown
Member

Summary

Part of adding FrankenPHP to OSS-Fuzz. The OSS-Fuzz Dockerfile/build.sh compile PHP from source and build the existing FuzzRequest native Go fuzz target (frankenphp_test.go) with compile_native_go_fuzzer, linking against a sanitizer-instrumented libphp.

Zend's own arena allocator reuses freed memory in ways that hide bugs from ASan/MSan. Disabling it (USE_ZEND_ALLOC=0) is already required for the sanitizer CI jobs in .github/workflows/sanitizers.yaml, but that env var can't reach a libFuzzer binary built by OSS-Fuzz the same way:

  • build.sh runs in a throwaway build container; ClusterFuzz later executes the compiled fuzzer as a fresh process on a different bot with no inherited environment.
  • The libFuzzer .options file's [env] section looks like it should fill the gap, but ClusterFuzz whitelists it down to two unrelated variables (AFL_DONT_DEFER, GODEBUG), so USE_ZEND_ALLOC there is silently dropped.

Setting it from an init() gated on the gofuzz build tag reaches the process before PHP starts, without affecting any non-fuzzing build (the CLI, the Caddy module, or anything else built by consumers of this module).

Test plan

  • Verified against a local checkout of google/oss-fuzz (infra/helper.py build_image/build_fuzzers) with a matching projects/frankenphp/{project.yaml,Dockerfile,build.sh}, to be submitted as a separate PR to that repo.

Zend's own arena allocator reuses freed memory in ways that hide bugs
from ASan/MSan; disabling it (USE_ZEND_ALLOC=0) is already required for
the sanitizer CI jobs (.github/workflows/sanitizers.yaml), but that env
var never reaches a libFuzzer binary built by OSS-Fuzz: build.sh runs in
a throwaway build container, and ClusterFuzz later execs the compiled
fuzzer as a fresh process on a different bot with no inherited env. The
libFuzzer .options file can't fill the gap either, since ClusterFuzz
whitelists its [env] section down to two unrelated variables.

Setting it from an init() gated on the "gofuzz" build tag reaches the
process before PHP starts, without touching any non-fuzzing build.
@dunglas
dunglas merged commit 29aa33d into main Aug 15, 2026
39 of 40 checks passed
@dunglas
dunglas deleted the oss-fuzz/disable-zend-alloc-for-fuzzing branch August 15, 2026 09:32
alexandre-daubois pushed a commit that referenced this pull request Aug 16, 2026
## Summary

`TestAddModuleWorkerViaAdminApi` POSTs a full config to the admin
`/load` endpoint, which swaps the HTTP listener for the new config, then
immediately GETs the newly added worker. A request racing that listener
swap can hit a reset connection (`EOF`) before the worker ever sees it —
seen on CI in
[#2604](#2604) (job
[94991854286](https://github.com/php/frankenphp/actions/runs/31876064293/job/94991854286)),
and matches the same class of flake fixed for the sibling autoscale
tests in #2413 (which references this test too, on #2412/#2381).

Retry only on connection-level errors (`err != nil` from `http.Get`),
not on the request/response itself: once a request actually reaches the
worker it always increments its counter, so retrying past a successful
connection would break the `requests:1` assertion.

## Test plan

- [x] `./go.sh -C caddy test ./...` passes
- [x] `./go.sh -C caddy test ./... -run TestAddModuleWorkerViaAdminApi
-count=5` passes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant