Skip to content

skip cffi objects reached as module attributes -- the int-as-pointer surface --blacklist misses - #268

Merged
devdanzin merged 1 commit into
mainfrom
cffi-attribute-objects-are-int-as-pointer
Sep 2, 2026
Merged

devdanzin merged 1 commit into
mainfrom
cffi-attribute-objects-are-int-as-pointer

Conversation

@devdanzin

Copy link
Copy Markdown
Owner

The last of the four items left open by the fleet_08 triage that I can act on alone. Flagged in
the fleet_05, _06, _07 and _08 reports without being applied, because it changes the default
fuzzing surface — applying it now that it has cost dirs in four consecutive fleets.

The gap

--blacklist excludes _cffi_backend / _rawffi / ctypes by module name. But PyPy's
stdlib hands out live cffi objects as module attributes, so the surface is reachable
regardless. Measured on PyPy 7.3.23:

resource.ffi   _ssl.ffi   _sqlite3._ffi   _lzma.ffi     _gdbm.ffi
_curses.ffi    curses.ffi _tkinter.tkffi  _sha3._ffi    _posixshmem.ffi   (+ matching .lib)

ffi.memmove(int, int, n) treats its arguments as raw pointers and dies by contract on
whatever integer it is handed — exactly as CPython's ctypes does on the same input. A fault
there is never a target defect. It is the same shape as the socket int-as-fd family fixed
in #266, one level down.

The change

skip_trivial_type is already emitted into every generated script and already consulted at all
three object/class dive sites, so this is one condition there.

It matches on the type's defining module, not on the attribute name. An OBJECT_BLACKLIST
entry for "ffi" / "lib" / "_ffi" / "tkffi" would match those names on unrelated targets
that legitimately expose them — there is a test pinning that distinction
(test_an_attribute_merely_NAMED_ffi_is_not_skipped).

Tests

The emitted function is source text, so the golden snapshot alone cannot catch a logic
error in it. The new tests parse skip_trivial_type out of the generated script, exec it,
and exercise it: a cffi-typed object is skipped, an ordinary object is not, the trivial types
still are, and an object merely named ffi is not.

The golden snapshot is updated; its only diff is this guard.

One trap worth recording

My first version of the comment used the words "segfault"/"segfaults", and
SelfNoiseVocabularyTests failed the build. That guard exists because help() echoes emitted
comments through inspect.getcomments, so fusil's own crash vocabulary inside a generated
comment manufactures a crash — a PyPy fleet kept a _sitebuiltins-segfault dir exactly that
way. The comment now says so in place, since that is the second time the trap has been walked
into.

Checks

1284 tests OK, ruff check and ruff format --check both clean.

…surface --blacklist misses

--blacklist excludes _cffi_backend / _rawffi / ctypes by MODULE NAME, but PyPy's
stdlib hands out live cffi objects as module ATTRIBUTES -- resource.ffi, _ssl.ffi,
_sqlite3._ffi, _lzma.ffi, _gdbm.ffi, _curses.ffi, _tkinter.tkffi, _sha3._ffi,
_posixshmem.ffi and their matching .lib -- so the surface is reachable regardless of
the module blacklist. ffi.memmove(int, int, n) treats its arguments as raw pointers
and dies by contract on whatever integer it is handed, exactly as CPython's ctypes
does, so a fault there is never a target defect.

Four consecutive PyPy fleets kept dirs from it (05, 06, 07, 08), which is why this
is being applied now rather than flagged a fifth time.

skip_trivial_type is already emitted into every generated script and already
consulted at all three object/class dive sites, so the change is one condition
there. It matches on the TYPE's defining module, not on the attribute name: an
OBJECT_BLACKLIST entry for "ffi"/"lib"/"_ffi"/"tkffi" would match those names on
unrelated targets that legitimately expose them, and there is a test pinning that
distinction.

Two things worth noting for future edits here:

The first version of the comment used the words "segfault"/"segfaults", and
SelfNoiseVocabularyTests caught it. That guard exists because help() echoes emitted
comments through inspect.getcomments, so fusil's own crash vocabulary in a generated
comment manufactures a crash -- the comment now says so in place, since this is the
second time that trap has been walked into.

The emitted function is SOURCE, so a golden snapshot cannot catch a logic error in
it. The new tests parse it out of the generated script, exec it, and exercise it.
@devdanzin
devdanzin merged commit cf8ed43 into main Sep 2, 2026
2 checks passed
@devdanzin
devdanzin deleted the cffi-attribute-objects-are-int-as-pointer branch September 2, 2026 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant