--oom-fuzz reported fusil's own bomb as a CPython contract violation - #273
Merged
Merged
Conversation
`oom_call`'s `except SystemError` exists to catch a PyCFunction contract
violation under allocation failure. But `SystemError` is one of the twelve
`_BOMB_EXCEPTIONS`, so every bomb built with `exc=None` -- `FailingIterator`,
`SuperBomb`, `DescriptorBomb`, `HiddenNameType`, and the rest -- raises it about
one firing in twelve, and the handler dutifully reported fusil's own object as a
finding with no C code involved at all.
The marker printed only the label, never the exception, so the two were
indistinguishable in a kept crash dir. That is what let it go unnoticed: an
--oom-foreign fleet of 68,463 sessions kept 410 SystemError dirs -- 74% of its
entire output -- and all 418 of their resolved labels had a random-exception bomb
passed to the firing call. Seven dirs replayed under the real shim, chosen to
include the hardest residue cases (`builtins.tuple`, `builtins.frozenset`,
`re.Scanner`), and every one was a bomb: `SystemError('fusil iter bomb')` or
`SystemError('fusil superbomb via __eq__')`. A control -- the same handler around
a pure-Python callee handed a bomb, no extension module anywhere -- fires the
marker at 15/200, matching SystemError's 1-in-12 share of the bomb tuple.
Every bomb message starts with "fusil " (samples/bomb_objects.py), which is the
discriminator, and the repr is now printed so a genuine one stays triageable from
stdout alone. Replaying the session behind one of those kept dirs goes from 4
markers to 0. Removing SystemError from `_BOMB_EXCEPTIONS` would have been the
wrong fix: a slot raising an unexpected SystemError is exactly the hostile input
that finds C code mishandling it -- the bug is reporting it as the target's.
The handler is emitted as source into every generated script, so the new tests
exec the emitted definition and drive it rather than asserting on snapshot text:
a bomb SystemError is suppressed, a target's is still reported with its repr, and
one merely mentioning "fusil" further into the message still reports.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPBSmN87d2BqUnrDbojUT1
devdanzin
deleted the
oom-systemerror-marker-fires-on-fusils-own-bomb
branch
September 5, 2026 21:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
oom_call'sexcept SystemErrorexists to catch a PyCFunction contract violation under allocation failure. ButSystemErroris one of the twelve_BOMB_EXCEPTIONS, so every bomb built withexc=None—FailingIterator,SuperBomb,DescriptorBomb,HiddenNameType, … — raises it about one firing in twelve, and the handler reported fusil's own object as a finding with no C code involved at all.The marker printed only the label, never the exception, so the two were indistinguishable in a kept crash dir.
How much this cost
Found while triaging
fusil-fleet-oom-01(--oom-foreign, 12 instances, 68,463 sessions, 3.7 h):oomclean(SystemError marker)OOM-0037(subinterp/structseq segv)OOM-0027(PyStackRef_BoolCheck)All 418 resolved labels in those 410 dirs had a random-exception bomb passed to the firing call.
Evidence
LD_PRELOADshim, chosen to include the hardest residue (builtins.tuple,builtins.frozenset,re.Scanner,tabnanny.Whitespace,trace._Ignore,gzip.GzipFile). Every one was a bomb:SystemError('fusil iter bomb')fromFailingIterator.__next__, orSystemError('fusil superbomb via __eq__').The fix
Every bomb message starts with
"fusil "(samples/bomb_objects.py), which is the discriminator. The repr is now printed so a genuine one stays triageable from stdout alone.Removing
SystemErrorfrom_BOMB_EXCEPTIONSwould have been the wrong fix: a slot raising an unexpectedSystemErroris exactly the hostile input that finds C code mishandling it — the bug is reporting it as the target's.Tests
The handler is emitted as source into every generated script, so the new tests exec the emitted definition and drive it rather than asserting on snapshot text: a bomb SystemError is suppressed, a target's is still reported with its repr,
MemoryErroris still swallowed, and one merely mentioning "fusil" further into the message still reports.ruff check+ruff format --checkclean; 1298 tests pass.🤖 Generated with Claude Code
https://claude.ai/code/session_01WPBSmN87d2BqUnrDbojUT1