Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions fusil/python/blacklists.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,31 @@
"sigwaitinfo",
"sigtimedwait",
},
# PyPy interpreter internals (__pypy__) that attack the fuzzer or the host rather than
# the target -- the "generated code kills its own session" class (see fusil #192).
# Everything else in __pypy__ is deliberately left fuzzable: it is PyPy-only surface with
# no CPython counterpart, which is the whole point of fuzzing PyPy.
"__pypy__": {
# Spawns an interp-level gdb *inside the session*. Observed live: gdb's own banner
# ("For bug reporting instructions...") lands in the captured stdout and scores on
# the "bug" word, so the session is kept as a crash that never happened.
"attach_gdb",
# "Executes a script of Python code in a given remote Python process." A fuzzer-chosen
# pid means arbitrary code injection into any process on the box -- including sibling
# fleet instances and the fuzzer itself.
"remote_exec",
# Installs a process-global hook invoked on every code-object creation; handing it one
# of fusil's bomb objects makes the rest of the session detonate on unrelated code.
"set_code_callback",
# Blocks: calls PyOS_InputHook() / stops under the reverse debugger.
"pyos_inputhook",
"revdb_stop",
# Documented as "for testing purposes, raise an interpreter-level ValueError.
# Should turn into a SystemError automatically" -- a deliberate self-test helper.
# "SystemError" is a 1.0 crash word, so with --test-private this alone tagged
# EVERY __pypy__ session as a crash. Manufactured signal, never a target bug.
"_internal_crash",
},
"_socket": SOCKET,
"socket": SOCKET,
"posix": POSIX,
Expand Down
15 changes: 15 additions & 0 deletions tests/python/test_blacklists.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ def test_module_class_keys_have_nonempty_parts(self):
class TestKnownEntriesPresent(unittest.TestCase):
"""Pin a few high-value entries so accidental deletion is caught."""

def test_pypy_self_harming_helpers_blacklisted(self):
# These attack the fuzzer or the host, not the target. attach_gdb was caught live on
# a PyPy 3.11 fleet: it runs gdb inside the session and gdb's banner scores on the
# "bug" word, manufacturing a crash. remote_exec injects code into an arbitrary pid.
self.assertLessEqual(
{"attach_gdb", "remote_exec", "set_code_callback", "_internal_crash"},
bl.BLACKLIST["__pypy__"],
)

def test_pypy_blacklist_stays_narrow(self):
# __pypy__ is PyPy-only surface with no CPython counterpart -- the reason to fuzz PyPy
# at all. Only the self-harming helpers belong here, never the interesting internals.
for keep in ("newdict", "strategy", "internal_repr", "intop", "move_to_end"):
self.assertNotIn(keep, bl.BLACKLIST["__pypy__"])

def test_sys_trace_hooks_blacklisted(self):
self.assertEqual(
bl.BLACKLIST["sys"] & {"settrace", "setprofile"}, {"settrace", "setprofile"}
Expand Down
Loading