Repository navigation
The skip-trivial guard printed "Skipping" and then fuzzed anyway - #275
Merged
Merged
Conversation
`skip_trivial_type` has correctly identified cffi objects since #268 -- a PyPy stdlib module hands out a live `FFI` as an attribute (`_curses_panel.ffi`, `_ssl.ffi`, `_lzma.ffi`, ... at least ten of them), and `type(ffi).__module__` really is `_cffi_backend`, so the check returns True. It just never mattered: two of the three emission sites put nothing in the guard's body except the "Skipping deep diving" print, and emitted the method fuzzing after the `if` statement rather than inside an `else`. The generated script therefore reported the skip and then called the object anyway: if skip_trivial_type(fuzz_target_module.ffi): print('Skipping deep diving on ...') # the entire body # General method fuzzing for fuzz_target_module.ffi try: res_obj0m1 = callMethod("obj0m1", fuzz_target_module.ffi, "typeof", ... `ffi.memmove()` and its siblings take their arguments as raw pointers and fault by contract on whatever they are handed -- exactly as ctypes does on CPython -- so a crash there is never a target defect. Five consecutive PyPy fleets kept dirs from it; the most recent is a `_curses_panel` SIGSEGV in fleet_10, whose last line before the fault is `[obj12m14] FFI.memmove()`. Both broken sites now open a real `else:`. The third site already did, which is why it never contributed. The plugin path is untouched: a dispatcher that opens its own trailing `else` still owns the fallback, and the new one is opened only when no dispatcher did. The golden snapshot moves accordingly -- the method-fuzzing block is one level deeper, inside the else. Asserting on the emitted text would not have caught this, because the print was always there. The new tests assert on the parsed structure instead: every `if skip_trivial_type(x):` must carry the work in its `orelse`, the taken branch must only report, and the emitted function must skip a `_cffi_backend`-typed instance while leaving an ordinary object alone. They fail on the pre-fix generator. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WPBSmN87d2BqUnrDbojUT1
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.
The bug
skip_trivial_typehas correctly identified cffi objects since #268. A PyPy stdlib module hands out a liveFFIas an attribute —_curses_panel.ffi,_ssl.ffi,_lzma.ffi, at least ten of them — andtype(ffi).__module__really is_cffi_backend, so the check returnsTrue.It just never mattered. Two of the three emission sites put nothing in the guard's body except the print, and emitted the method fuzzing after the
ifrather than inside anelse:So the script reported the skip and then called the object anyway.
ffi.memmove()and its siblings take their arguments as raw pointers and fault by contract on whatever they are handed — exactly asctypesdoes on CPython — so a crash there is never a target defect. Five consecutive PyPy fleets kept dirs from this; the most recent is a_curses_panelSIGSEGV in fleet_10 whose last line before the fault is[obj12m14] FFI.memmove().The fix
Both broken sites now open a real
else:. The third already did, which is why it never contributed.The plugin path is untouched: a dispatcher that opens its own trailing
elsestill owns the fallback, and the new one is opened only when no dispatcher did. Apasskeeps the block valid when an object turns out to have no methods to fuzz.The golden snapshot moves accordingly — the method-fuzzing block is one level deeper, inside the else.
Tests
Asserting on the emitted text would not have caught this, because the print was always there. The new tests assert on the parsed structure:
if skip_trivial_type(x):carries the work in itsorelse_cffi_backend-typed instance and leaves an ordinary object aloneAll three fail on the pre-fix generator (verified by stashing the fix). 1303 tests pass;
ruff check+ruff format --checkclean.🤖 Generated with Claude Code
https://claude.ai/code/session_01WPBSmN87d2BqUnrDbojUT1