Skip to content

lua: fix broken build — remove utf8_*_test targets blocking coverage#54

Open
tc-agent wants to merge 2 commits into
masterfrom
lua-fix-coverage-build
Open

lua: fix broken build — remove utf8_*_test targets blocking coverage#54
tc-agent wants to merge 2 commits into
masterfrom
lua-fix-coverage-build

Conversation

@tc-agent

@tc-agent tc-agent commented May 9, 2026

Copy link
Copy Markdown
Owner

Status: advisory stopgap — maintainer decision requested

This restores the long-broken lua coverage build, but it does so by disabling production fuzzing of 5 utf8_* Lua-API targets (see impact section). It directly overlaps @ligurio's in-flight coverage work (#14875 / #14859). It is offered as an optional stopgap; the durable fix is infra-side and tracked on #14859. Please decide whether to take this now or wait for the infra fix — not a unilateral merge request.

Summary

Coverage builds for lua have failed every day since 2026-04-12. Last successful: 2026-04-11. Status feed: https://oss-fuzz-build-logs.storage.googleapis.com/index.html#lua.

The coverage runner extracts every /corpus/<target>.zip before invoking coverage (build_and_run_coverage.py):

for f in /corpus/*.zip; do
  unzip -q $f -d ${f%.*} || (echo "Failed to unpack..." && exit 1);
done && coverage || (echo "$failure_msg" && false)

(echo ... && exit 1) is a subshell, so exit 1 does not break the loop — the loop's exit status is the final iteration's unzip status. The corpus set is built from targets.list.address (build_lib._get_targets_list, consumed by download_corpora_steps). ClusterFuzz backups for many luzer-based targets (added in #14610) are 0-byte, and utf8_offset_test sorts alphabetically last, so the final unzip fails, && coverage short-circuits, and no report is generated.

Fix

rm -f $OUT/utf8_* in the address build (the script exits earlier for SANITIZER=coverage). This makes torture_test the alphabetically-last target.

Security / production-fuzzing impact (please read)

targets.list.address is the production libFuzzer+ASan target list — ClusterFuzz fuzzes exactly what is in that $OUT. This change therefore stops OSS-Fuzz from fuzzing the 5 utf8_* Lua-API targets (utf8_char/codepoint/codes/len/offset_test — attacker-controlled byte-string parsing) until reverted. Stated explicitly in the inline build.sh comment too.

Glob scope confirmed: all 5 matched names are luzer Lua-API wrappers from tests/lapi/. The C-API tests (tests/capi/) are named luaL_*, lua_*, torture_test, plus the standalone fuzz_lua; none use the utf8_ prefix, so rm -f $OUT/utf8_* cannot catch a C-API target. This matches the production list: sort | awk '$0 > "torture_test"' returns exactly those 5.

Why no less-destructive option exists within a project build.sh:

  • Corpus zips are ClusterFuzz cloud backups in /corpus/; a project build.sh cannot write them or repair the 0-byte ones ($OUT/<t>_seed_corpus.zip seeds fuzzing but does not fix the broken cloud backups the coverage runner extracts).
  • The non-fatal-unzip loop lives in OSS-Fuzz infra, not the project.
  • Only the alphabetically-last target gates the loop; the ~80 other 0-byte luzer backups extract earlier and are harmless. The only lever from build.sh is which binaries land in $OUT. Renaming instead of deleting was considered but the luzer wrapper scripts have internal name/path coupling that makes an in-build.sh rename fragile (risking check_build failures) for no gain — renamed targets would still have 0-byte cloud backups.
  • Net: a fully-broken coverage report (zero visibility for all 16 surviving C-API/fuzz_lua targets, indefinitely) vs. temporarily pausing 5 luzer targets whose corpora are already not preserved by the broken pruning.

Durable fix (out of scope here)

Make the unzip non-fatal in build_and_run_coverage.py (continue past a bad /corpus/*.zip instead of letting the loop's last iteration gate coverage). This also unblocks every other project hit by stale ClusterFuzz pruning (e.g. qemu, broken since 2023-11-13). It belongs in OSS-Fuzz infra and should be tracked under the existing Lua-coverage umbrella issue #14859 (already referenced at build.sh:148). This PR is the project-side stopgap only.

Coordination with in-flight maintainer work

@ligurio has directly-overlapping active work — please advise whether to take this stopgap or wait:

  • #14875 / issue #14859: "Support C/C++ coverage for Lua tests" (the reason coverage is gated at build.sh:148).
  • #15446 (merged 2026-05-01): "lua: enable quiet mode for zip" — same zip/unzip area.

Evidence the fix works

targets.list.address (102 entries) — the only entries sorting strictly after torture_test are exactly the five removed wrappers:

$ curl -s .../targets.list.address | sort | awk '$0 > "torture_test"'
utf8_char_test
utf8_codepoint_test
utf8_codes_test
utf8_len_test
utf8_offset_test

torture_test's backup is valid/non-empty: in the failing build log, Step #6 has no torture_test.zip line — not among the 74 cannot find zipfile directory failures nor the 12 zipfile is empty warnings. unzip -q is silent only on success, so it extracts with exit 0; after removing utf8_* it is the loop's final iteration, which therefore exits 0 and coverage runs.

Fragility

Alphabetic-tail workaround: any future luzer target sorting after torture_test (name uz) re-breaks coverage until the durable infra fix lands. Stated inline in build.sh.

Coverage baseline

Harnesses are untouched; the surviving 16 C-API/fuzz_lua targets keep their existing coverage. New coverage is not measurable until this lands (the failure is in the cloud coverage runner, not locally reproducible). Frozen-at-2026-04-11 Fuzz Introspector snapshot: https://introspector.oss-fuzz.com/project-profile?project=lua.

@github-actions

github-actions Bot commented May 9, 2026

Copy link
Copy Markdown

Fuzzing Coverage Report

Tested: project lua · base 26deef8 → head f8a4b6d · 300s total fuzz budget · updated 2026-05-28 02:07 UTC · workflow run

Metric Before After Delta
Static reachability 61.4% (821/1337) 61.4% (821/1337) +0.0%

Δ = (after − before) / before, to accommodate that denominators may change. "new" when before is 0; "deleted" when after is 0.

@tc-agent
tc-agent force-pushed the master branch 3 times, most recently from 0c732ae to 576129c Compare May 10, 2026 07:35
@tc-agent
tc-agent force-pushed the lua-fix-coverage-build branch from 186e3c0 to 7bc2a28 Compare May 10, 2026 07:35
@tc-agent
tc-agent force-pushed the master branch 25 times, most recently from 55041f5 to da881b1 Compare May 14, 2026 13:17
@tc-agent
tc-agent force-pushed the lua-fix-coverage-build branch from 7bc2a28 to 7f34984 Compare May 16, 2026 15:43
@tc-agent
tc-agent force-pushed the master branch 3 times, most recently from c540264 to b54c0d2 Compare May 17, 2026 07:07
@tc-agent
tc-agent force-pushed the lua-fix-coverage-build branch from 7f34984 to 07737c5 Compare May 17, 2026 07:07
@tc-agent
tc-agent force-pushed the master branch 2 times, most recently from 1b028e2 to a7386df Compare May 17, 2026 09:43
@tc-agent
tc-agent force-pushed the lua-fix-coverage-build branch from 07737c5 to 83592ff Compare May 17, 2026 09:45
@tc-agent
tc-agent force-pushed the master branch 5 times, most recently from 6125235 to e512e7e Compare May 27, 2026 06:33
@tc-agent
tc-agent force-pushed the lua-fix-coverage-build branch from 83592ff to 9995b24 Compare May 27, 2026 07:53
@tc-agent
tc-agent force-pushed the master branch 5 times, most recently from b5fd10c to 712a52f Compare May 27, 2026 16:16
@tc-agent
tc-agent force-pushed the lua-fix-coverage-build branch from 9995b24 to f8a4b6d Compare May 28, 2026 01:25
@tc-agent
tc-agent force-pushed the master branch 2 times, most recently from a7587cd to b952f62 Compare May 28, 2026 02:55
@tc-agent tc-agent added the wontfix This will not be worked on label May 28, 2026
@tc-agent
tc-agent force-pushed the master branch 4 times, most recently from af7f9a7 to 806b281 Compare May 28, 2026 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wontfix This will not be worked on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant