mirror of
https://github.com/trailofbits/buttercup
synced 2026-06-21 14:11:39 +00:00
Fix fuzzer-runner missing transitive dependency and add tests (#459)
* Use openlit <1.36.6 Openlit >=1.36.6 has a bug with langgraph instrumentation. Also add a test to seed-gen for when openlit is enabled * Link to issue * Fix CoverageBot.run_task and add test cases * Add setuptools as an explicit dependency This is because a transitive dependency via clusterfuzz depends on it * Appease ruff
This commit is contained in:
@@ -9,6 +9,7 @@ dependencies = [
|
||||
"common",
|
||||
"clusterfuzz ==2.6.0",
|
||||
"pydantic ~=2.11.7",
|
||||
"setuptools", # Required for pkg_resources used by google-cloud-ndb (clusterfuzz dep)
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
def test_empty():
|
||||
pass
|
||||
@@ -0,0 +1,83 @@
|
||||
"""Tests for the fuzzer runner module."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from buttercup.fuzzer_runner.runner import Conf, Runner
|
||||
|
||||
|
||||
class TestRunner:
|
||||
"""Tests for the Runner class."""
|
||||
|
||||
@patch("buttercup.fuzzer_runner.runner.patched_temp_dir")
|
||||
@patch("buttercup.fuzzer_runner.runner.scratch_cwd")
|
||||
@patch("os.makedirs")
|
||||
def test_run_fuzzer_initializes_engine(self, mock_makedirs, mock_scratch_cwd, mock_patched_temp_dir):
|
||||
"""Test run_fuzzer"""
|
||||
from buttercup.common.types import FuzzConfiguration
|
||||
from clusterfuzz._internal.bot.fuzzers.libFuzzer import engine as libfuzzer_engine
|
||||
|
||||
mock_patched_temp_dir.return_value.__enter__ = MagicMock()
|
||||
mock_patched_temp_dir.return_value.__exit__ = MagicMock(return_value=False)
|
||||
mock_scratch_cwd.return_value.__enter__ = MagicMock()
|
||||
mock_scratch_cwd.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
# Mock the engine methods that would fail without a real fuzzer binary
|
||||
mock_opts = MagicMock()
|
||||
mock_opts.corpus_dir = "/corpus"
|
||||
mock_opts.arguments = []
|
||||
mock_opts.strategies = []
|
||||
|
||||
mock_result = MagicMock()
|
||||
mock_result.crashes = []
|
||||
mock_result.logs = "test"
|
||||
mock_result.stats = {}
|
||||
mock_result.time_executed = 1.0
|
||||
mock_result.timed_out = False
|
||||
|
||||
with (
|
||||
patch.object(libfuzzer_engine.Engine, "prepare", return_value=mock_opts),
|
||||
patch.object(libfuzzer_engine.Engine, "fuzz", return_value=mock_result),
|
||||
):
|
||||
conf = Conf(timeout=60)
|
||||
runner = Runner(conf)
|
||||
fuzzconf = FuzzConfiguration(
|
||||
corpus_dir="/corpus",
|
||||
target_path="/target",
|
||||
engine="libfuzzer",
|
||||
sanitizer="address",
|
||||
)
|
||||
|
||||
result = runner.run_fuzzer(fuzzconf)
|
||||
|
||||
assert result.crashes == []
|
||||
assert result.timed_out is False
|
||||
|
||||
@patch("buttercup.fuzzer_runner.runner.scratch_dir")
|
||||
@patch("buttercup.fuzzer_runner.runner.patched_temp_dir")
|
||||
@patch("buttercup.fuzzer_runner.runner.scratch_cwd")
|
||||
def test_merge_corpus_initializes_engine(self, mock_scratch_cwd, mock_patched_temp_dir, mock_scratch_dir):
|
||||
"""Test merge_corpus."""
|
||||
from buttercup.common.types import FuzzConfiguration
|
||||
from clusterfuzz._internal.bot.fuzzers.libFuzzer import engine as libfuzzer_engine
|
||||
|
||||
mock_patched_temp_dir.return_value.__enter__ = MagicMock()
|
||||
mock_patched_temp_dir.return_value.__exit__ = MagicMock(return_value=False)
|
||||
mock_scratch_cwd.return_value.__enter__ = MagicMock()
|
||||
mock_scratch_cwd.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
mock_td = MagicMock()
|
||||
mock_td.path = "/tmp/scratch"
|
||||
mock_scratch_dir.return_value.__enter__ = MagicMock(return_value=mock_td)
|
||||
mock_scratch_dir.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
with patch.object(libfuzzer_engine.Engine, "minimize_corpus"):
|
||||
conf = Conf(timeout=60)
|
||||
runner = Runner(conf)
|
||||
fuzzconf = FuzzConfiguration(
|
||||
corpus_dir="/corpus",
|
||||
target_path="/target",
|
||||
engine="libfuzzer",
|
||||
sanitizer="address",
|
||||
)
|
||||
|
||||
runner.merge_corpus(fuzzconf, "/output")
|
||||
Generated
+11
@@ -264,6 +264,7 @@ dependencies = [
|
||||
{ name = "clusterfuzz" },
|
||||
{ name = "common" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "setuptools" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
@@ -281,6 +282,7 @@ requires-dist = [
|
||||
{ name = "clusterfuzz", specifier = "==2.6.0" },
|
||||
{ name = "common", editable = "../common" },
|
||||
{ name = "pydantic", specifier = "~=2.11.7" },
|
||||
{ name = "setuptools" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
@@ -1252,6 +1254,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/6a/40fee331a52339926a92e17ae748827270b288a35ef4a15c9c8f2ec54715/ruff-0.14.14-py3-none-win_arm64.whl", hash = "sha256:56e6981a98b13a32236a72a8da421d7839221fa308b223b9283312312e5ac76c", size = 10920448, upload-time = "2026-01-22T22:30:15.417Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "80.10.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/95/faf61eb8363f26aa7e1d762267a8d602a1b26d4f3a1e758e92cb3cb8b054/setuptools-80.10.2.tar.gz", hash = "sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70", size = 1200343, upload-time = "2026-01-25T22:38:17.252Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/94/b8/f1f62a5e3c0ad2ff1d189590bfa4c46b4f3b6e49cef6f26c6ee4e575394d/setuptools-80.10.2-py3-none-any.whl", hash = "sha256:95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173", size = 1064234, upload-time = "2026-01-25T22:38:15.216Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.17.0"
|
||||
|
||||
Reference in New Issue
Block a user