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
6 changes: 6 additions & 0 deletions fusil/python/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,12 @@ def setupProject(self) -> None:
# single PyPy fleet.
r"fusil (bomb|iter bomb|superbomb|fileno bomb|hidden name|descriptor (get|set)"
r"|stateful hash|instancecheck|junk return|monitoring callback bomb)",
# http.cookiejar warns "http.cookiejar bug!" (its own words) when it meets a
# malformed cookie -- routine for a fuzzer. The message contains the "bug" word
# (0.10), so on its own it is harmless, but combined with another weak signal it
# pushes a boring session over the threshold: 6 kept dirs in one PyPy fleet. It
# is the target's benign diagnostic, not a target defect.
r"http\.cookiejar bug!",
# The --new-uninit region prints a progress marker per poked type,
# e.g. "[NEW-UNINIT] poking SystemError". The type name is arbitrary and
# routinely collides with a crash word ("SystemError" -> a 1.0 hit) or, worse,
Expand Down
7 changes: 7 additions & 0 deletions fusil/python/blacklists.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,13 @@
# _testmultiphase (foo/Example/Str) is real multi-phase-init surface worth fuzzing, and on
# PyPy it exercises the cpyext C-API emulation layer.
"_testmultiphase": {"call_state_registration_func"},
# asyncio.runners.Runner._on_sigint is the SIGINT handler the Runner installs; called
# directly as a fuzz target it unconditionally `raise KeyboardInterrupt()`. Like
# signal.default_int_handler, that is a BaseException, so it escapes the generated
# script's `except Exception` handlers and kills the session (the #192 class). It was
# 29 of 53 kept dirs -- 55% -- in one PyPy fleet, reached because --test-private exposes
# the underscore-prefixed method.
"asyncio.runners:Runner": {"_on_sigint"},
"_socket": SOCKET,
"socket": SOCKET,
"posix": POSIX,
Expand Down
6 changes: 6 additions & 0 deletions tests/python/test_blacklists.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ def test_testmultiphase_state_func_blacklisted_but_module_is_not(self):
for keep in ("foo", "Example", "Str"):
self.assertNotIn(keep, bl.BLACKLIST["_testmultiphase"])

def test_asyncio_runner_on_sigint_blacklisted(self):
# Same class as default_int_handler: it raises KeyboardInterrupt, a BaseException,
# which escapes the generated script's handlers and kills the session. Reached only
# because --test-private exposes the underscore-prefixed method.
self.assertIn("_on_sigint", bl.BLACKLIST["asyncio.runners:Runner"])

def test_default_int_handler_blacklisted(self):
# It raises KeyboardInterrupt, a BaseException, which escapes the generated script's
# `except Exception` handlers and kills the session outright (the #192 class).
Expand Down
17 changes: 17 additions & 0 deletions tests/test_file_watch.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,20 @@ def test_ignore_regex_covers_every_raised_bomb_signature(self):
"fusil/python/__init__.py, so they will be scored as target crashes: "
+ ", ".join(uncovered),
)


class TestCookiejarWarningIgnored(unittest.TestCase):
"""http.cookiejar's own "bug!" warning must not push a boring session over the threshold.

The message is the target's benign diagnostic for a malformed cookie -- routine input for
a fuzzer -- but it contains the "bug" word (0.10). On its own that is harmless; combined
with another weak signal it kept 6 dirs in one PyPy fleet.
"""

def test_cookiejar_warning_is_ignored_but_a_real_hit_still_scores(self):
w = _watch(words={"bug": 0.10, "segfault": 1.0})
w.ignoreRegex(r"http\.cookiejar bug!")
self.assertIsNone(w.processLine(b"x.py:1369: UserWarning: http.cookiejar bug!"))
self.assertEqual(w.score, 0.0)
w.processLine(b"got a segfault here")
self.assertEqual(w.score, 1.0)
Loading