Repository navigation
fix: stop CoroutineStateCorruptor shadowing global sys in the harness - #878
Merged
Merged
Conversation
CoroutineStateCorruptor injected `import sys` into the harness function body. A function-local `import sys` makes `sys` local to the whole function, so every `[fN]`/`[EVIL]` coverage marker (`print(..., file=sys.stderr)`) that runs before it raised `UnboundLocalError` — killing the child before the JIT warmed and scoring it 0.0. The injected imports also accumulated across generations (FuzzerSetupNormalizer did not strip them), poisoning saved corpus files. A real run wasted ~20% of children on this; a reproduction on the unfixed code showed ~10-12%, dropping to 0% after the fix (including on already-poisoned corpus). - CoroutineStateCorruptor now injects only `import asyncio` (the coroutine needs it; sys is always module-global via the boilerplate) and adjusts the injection point from 2 to 1 prepended imports. - FuzzerSetupNormalizer.visit_Import now also strips `import sys`, so existing poisoned corpus files self-heal on their next mutation and the failure class is neutralized regardless of source. Closes #877 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 1, 2026
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.
Summary
CoroutineStateCorruptorinjected a function-localimport sysinto the harness, which shadows the module-globalsys. Everysys.stderrcoverage marker that runs before it then raisedUnboundLocalError, killing the child before the JIT warmed → score 0.0.FuzzerSetupNormalizerstrippedgc/randombut notsys), so the breakage got baked into saved corpus files.import asyncio(which the coroutine needs;sysis always module-global via the boilerplate), andFuzzerSetupNormalizernow stripsimport sysso already-poisoned corpus files self-heal on their next mutation.Impact
This was ~47% of all 0.0-score children in a real run (
jit_run9): aNameError: 'sys'half (fixed earlier by #867) and anUnboundLocalError: 'sys'half (this PR, ~20% of children). A reproduction driving the currentMutationControllerover the real corpus:UnboundLocalError: sysjit_run9corpus files, confirming the normalizer heals them.Test plan
test_injects_asyncio_but_not_sys— mutator injectsasyncio, notsys.test_fuzzer_setup_normalizer_strips_sys_import— module-levelimport sysis stripped.test_normalizer_heals_function_local_import_sys— a harness that usessysbefore a function-localimport sysraisesUnboundLocalErrorbefore normalization and runs cleanly after.ruffclean;mypy lafleur/clean on changed files.Closes #877
🤖 Generated with Claude Code