GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||
GeezerVison is showing github.com — CI: UBSan runs GIL-only and never against the JIT; two configurations already shipped by distros are unsanitized · Issue #154927 · python/cpython Open Labels infraCI, GitHub Actions, buildbots, Dependabot, etc.CI, GitHub Actions, buildbots, Dependabot, etc.type-featureA feature request or enhancementA feature request or enhancement DescriptionFeature or enhancementProposalThe UBSan job in 1. UBSan ×
|
| UB reports | test failures | failing files | |
|---|---|---|---|
| before | 1762 | 529 | 61 |
| after #154915 | 0 | 0 | 0 |
Once #154915 lands, this configuration is green, so adding it is a regression guard rather than a source of new work.
--enable-experimental-jitjit.yml builds the JIT in several configurations and tail-call.yml builds --with-tail-call-interp, but neither is ever combined with a sanitizer. The JIT's own C code — the stencil patcher in Python/jit.c, and the tier-2 optimiser in Python/optimizer*.c which only compiles under -D_Py_TIER2=1 — is therefore never sanitized in CI.
This one has already proven productive when done by hand: gh-139269 (an unaligned uint64_t store in Python/jit.c's patch_* functions, which segfaulted release builds) was found by building --enable-experimental-jit with -fsanitize=address,undefined, and gh-142476 was an ASan-found leak in allocate_executor.
I ran the full test suite against a machine-code JIT build under UBSan, with every entry in Tools/ubsan/suppressions.txt disabled: clean, zero reports, 51,459 tests across 493 files, 4m50s. Verified non-vacuous — _testinternalcapi.get_jit_backend() returns jit and a hot loop produces real machine-code ranges, so this was the copy-and-patch JIT rather than a silent fallback to the uop interpreter.
Since it is already green, this is also a pure regression guard.
local-bounds is enabled nowhere. --with-undefined-behavior-sanitizer injects plain -fsanitize=undefined, and local-bounds is not in that group even though it detects genuine UB. I built with it on and ran the full suite: zero findings, including no false positives from the trailing variable-length array idiom, which was the obvious risk. It looks free to add.float-divide-by-zero (also not in the group) yields exactly one hit, Modules/expat/xmlparse.c:869, in vendored libexpat, which deliberately relies on IEEE-754 +inf and documents that in a comment. Not worth enabling without excluding expat.The usual objection to widening the matrix is build time. For reference, a full PGO + ThinLTO + UBSan build — the heaviest combination I tried, including the instrumented build, the profile run, the rebuild and the ThinLTO link — took 9 min 43 s at --jobs=8. A plain UBSan build is far cheaper, and the JIT suite run above took under five minutes.
(That PGO/LTO configuration found nothing new, incidentally. It is worth noting only because --enable-optimizations and --with-lto appear in no workflow at all, while Arch, Debian and python-build-standalone all ship them. UBSan's checks are source-level, so PGO/LTO mostly changes which UB is reached; miscompilation from UB would show up as test failures rather than sanitizer reports, which is a different exercise.)
This is a follow-up to gh-148286.
How well is this covered by Buildbots? I'm also not sure we can expand it to the JIT currently with the development pause, it does fall under a new feature (albeit an infra one).
Good questions — I checked the fleet rather than guessing.
Corrections. This comment has been edited twice, and I would rather the
record show that than quietly read as if it were right first time.2026-08-08: the UBSan row of the table below said 0. There are 20. I
matched on the builder name "UBSan"; they are called "Usan".2026-08-09: the two measurements quoted at the bottom did not survive
re-running. Both are corrected there, and the issue body has been updated
with the details.
Querying buildbot.python.org/api/v2/builders (1588 builders, all
branches and PR builders included), matching on the ubsan/asan/nogil
tags rather than on builder names:
| sanitizer / config | builders |
|---|---|
| UBSan | 20 |
| TSan | 0 |
| ASan | 34 |
| free-threading | 136 |
| JIT | 0 |
The UBSan builders are AMD64 Arch Linux Usan {3.9 … 3.15, 3.x, PR} and
AMD64 Arch Linux Usan Function {3.9 … 3.15, 3.x, PR}, all tagged
clang, ubsan, sanitizer. They are active, not vestigial: on the
development branch, AMD64 Arch Linux Usan 3.x and
AMD64 Arch Linux Usan Function 3.x both last built green on 2026-08-08.
(The one exception is AMD64 Arch Linux Usan PR, which last ran 2026-01-05
and failed in its git/clean steps rather than in any test — its worker is
online and its sibling Usan Function PR ran fine on 2026-07-30, so this
looks like a stale workspace on a builder that only runs when a PR requests
it.)
So buildbots do cover UBSan, on Arch with clang, across every active
branch — and that partly duplicates the GitHub Actions job. I was wrong to
say otherwise.
What is still true, and is what this issue asks for: none of those twenty
builders carries a nogil or jit tag. UBSan × free-threading and
UBSan × JIT are covered nowhere — not in GitHub Actions, not on the
buildbots. That matters concretely here, because the uniqueid.c bug lives
in code that only compiles under Py_GIL_DISABLED, so no existing UBSan
builder could have caught it, however many of them there are.
Worth adding, since it bears on how much the sanitizer job is worth:
UBSan only makes a selected set of undefined behaviour observable, and
only when you build for it. None of the three bugs behind this proposal
misbehaves in an ordinary build — I checked. So sanitizer coverage is
not redundant with the ordinary Buildbot fleet; it is the only thing
that sees these at all.
Fair, and I do not want to argue release policy. Happy to split this:
halt_on_error=1, the free-threaded build aborts during interpreterResult: SUCCESS, 51,517 tests, no runtime error: reports.If splitting sounds right I will retitle this issue to the
free-threading half and open a separate one for the JIT.