Skip to content

Commit

Permalink
Standardize and sanitize FM tool value
Browse files Browse the repository at this point in the history
- Sanitize FM tool value (remove whitespace and lower case)
- Display tool when reporting result to FM
- Use grizzly-(adapter.name) as default tool value when fuzzing
- Add 'grizzly-' prefix to adapter name in grizzly.replay
- Add 'grizzly-reducer' fallback in grizzly.reduce
- tool value from ~/.fuzzmanagerconf is no longer used
  • Loading branch information
tysmith committed Nov 28, 2022
1 parent 4c98e13 commit 2486742
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 21 deletions.
7 changes: 5 additions & 2 deletions grizzly/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,11 @@ def sanity_check(self, args):
if args.time_limit and args.timeout and args.timeout < args.time_limit:
self.parser.error("--timeout must be >= --time-limit")

if args.tool is not None and not args.fuzzmanager:
self.parser.error("--tool requires --fuzzmanager")
if args.tool:
if not args.fuzzmanager:
self.parser.error("--tool requires --fuzzmanager")
if len(args.tool.split()) != 1 or args.tool.strip() != args.tool:
self.parser.error("--tool cannot contain whitespace")

if args.xvfb: # pragma: no cover
args.headless = "xvfb"
Expand Down
19 changes: 12 additions & 7 deletions grizzly/common/reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,15 @@ class FuzzManagerReporter(Reporter):

__slots__ = ("_extra_metadata", "force_report", "quality", "tool")

def __init__(self, tool=None):
def __init__(self, tool):
super().__init__()
assert isinstance(tool, str)
self._extra_metadata = {}
self.force_report = False
self.quality = Quality.UNREDUCED
self.tool = tool # optional tool name
# remove whitespace and use only lowercase
self.tool = "-".join(tool.lower().split())
assert self.tool, "tool value cannot be empty"

def _post_submit(self):
self._extra_metadata.clear()
Expand Down Expand Up @@ -237,7 +240,7 @@ def _ignored(report):
return log_data.startswith("VEX temporary storage exhausted.")

def _submit_report(self, report, test_cases):
collector = Collector()
collector = Collector(tool=self.tool)

if not self.force_report:
if collector.sigCacheDir and Path(collector.sigCacheDir).is_dir():
Expand Down Expand Up @@ -299,14 +302,16 @@ def _submit_report(self, report, test_cases):
for entry in report.path.rglob("*"):
if entry.is_file():
zip_fp.write(entry, arcname=entry.relative_to(report.path))
# override tool name if specified
if self.tool is not None:
collector.tool = self.tool

# submit results to the FuzzManager server
new_entry = collector.submit(
report.crash_info, testCase=zip_name, testCaseQuality=self.quality.value
)
LOG.info("Logged %d (%s)", new_entry["id"], self.quality.name)
LOG.info(
"Reported: %d, %s, %s",
new_entry["id"],
self.quality.name,
collector.tool,
)

return new_entry["id"]
22 changes: 21 additions & 1 deletion grizzly/common/test_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ def test_fuzzmanager_reporter_02(
{"frequent": frequent, "shortDescription": "[@ test]"},
)
fake_collector.return_value.sigCacheDir = str(tmp_path) if sig_cache else None
fake_collector.return_value.tool = "fake-tool"
log_path = tmp_path / "log_path"
log_path.mkdir()
(log_path / "log_ffp_worker_blah.txt").touch()
Expand All @@ -204,10 +205,11 @@ def test_fuzzmanager_reporter_02(
test_cases = []
if tests:
test_cases.append(fake_test)
reporter = FuzzManagerReporter("fake_bin")
reporter = FuzzManagerReporter("fake-tool")
reporter.force_report = force
reporter.submit(test_cases, Report(log_path, "fake_bin", is_hang=True))
assert not log_path.is_dir()
assert fake_collector.call_args == ({"tool": "fake-tool"},)
if (frequent and not force) or ignored:
assert fake_collector.return_value.submit.call_count == 0
assert fake_test.dump.call_count == 0
Expand All @@ -232,6 +234,24 @@ def test_fuzzmanager_reporter_03(mocker, tmp_path):
assert FuzzManagerReporter._ignored(report)


@mark.parametrize(
"tool, sanitized",
[
# no whitespace
("test-tool", "test-tool"),
# whitespace
("test tool", "test-tool"),
# whitespace
("test\t\r\n\vtool", "test-tool"),
# mixed case
("TeSt-ToOl", "test-tool"),
],
)
def test_fuzzmanager_reporter_04(tool, sanitized):
"""test FuzzManagerReporter() sanitizing tool"""
assert FuzzManagerReporter(tool).tool == sanitized


def test_failed_launch_reporter_01(mocker, tmp_path):
"""test FailedLaunchReporter()"""
gtp = tmp_path / "grizzly"
Expand Down
4 changes: 2 additions & 2 deletions grizzly/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ def main(args):

LOG.debug("initializing the Reporter")
if args.fuzzmanager:
LOG.info("Results will be reported via FuzzManager")
reporter = FuzzManagerReporter(tool=args.tool)
reporter = FuzzManagerReporter(args.tool or f"grizzly-{adapter.name}")
LOG.info("Results will be reported via FuzzManager (%s)", reporter.tool)
else:
reporter = FilesystemReporter(args.logs / "results")
LOG.info("Results will be stored in '%s'", reporter.report_path)
Expand Down
9 changes: 3 additions & 6 deletions grizzly/reduce/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def __init__(
self._original_use_harness = use_harness
self._report_to_fuzzmanager = report_to_fuzzmanager
self._report_periodically = report_period
self._report_tool = tool
self._report_tool = tool or "grizzly-reducer"
self._signature = signature
self._signature_desc = signature_desc
self._static_timeout = expect_hang or static_timeout
Expand Down Expand Up @@ -801,12 +801,9 @@ def main(cls, args):
LOG.error("Error: %s", str(exc))
return Exit.ERROR

if args.tool is None and testcases[0].adapter_name is not None:
LOG.warning(
"Setting default --tool=grizzly-%s from testcase",
testcases[0].adapter_name,
)
if not args.tool and testcases[0].adapter_name:
args.tool = f"grizzly-{testcases[0].adapter_name}"
LOG.warning("Setting default --tool=%s from testcase", args.tool)

expect_hang = ReplayManager.expect_hang(args.ignore, signature, testcases)

Expand Down
4 changes: 2 additions & 2 deletions grizzly/replay/replay.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ def report_to_fuzzmanager(results, tests, tool=None):
Returns:
None
"""
if tests and not tool:
tool = tests[0].adapter_name
if not tool and tests and tests[0].adapter_name:
tool = f"grizzly-{tests[0].adapter_name}"
reporter = FuzzManagerReporter(tool or "grizzly-replay")
for result in results:
# always report expected results
Expand Down
3 changes: 2 additions & 1 deletion grizzly/replay/test_replay.py
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,8 @@ def test_replay_23(mocker):
]
test = mocker.Mock(spec_set=TestCase, adapter_name="test-tool-name")
ReplayManager.report_to_fuzzmanager(results, [test])
assert reporter.call_args == (("test-tool-name",),)
# check 'grizzy-' prefix is added
assert reporter.call_args == (("grizzly-test-tool-name",),)
assert reporter.return_value.submit.call_count == 2
reporter.reset_mock()
# with reports and no tests
Expand Down
12 changes: 12 additions & 0 deletions grizzly/test_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,18 @@ def test_common_args_02(capsys, mocker, args, msg, idx):
"error: --tool requires --fuzzmanager",
["targ1"],
),
# test invalid tool usage
(
["--platform", "targ1", "--fuzzmanager", "--tool", "x x"],
"error: --tool cannot contain whitespace",
["targ1"],
),
# test invalid tool usage
(
["--platform", "targ1", "--fuzzmanager", "--tool", " x"],
"error: --tool cannot contain whitespace",
["targ1"],
),
# test invalid launch-attempts value
(
["--launch-attempts", "0"],
Expand Down

0 comments on commit 2486742

Please sign in to comment.