aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Oliver Chang <oliverchang@users.noreply.github.com>2021-10-27 12:24:26 +1100
committerGravatar GitHub <noreply@github.com>2021-10-27 12:24:26 +1100
commitf460c03c8a4d035b2f857d23351545408d4afaa6 (patch)
treec54a96b7ab0ba1c5e42f7e2e714d587189867679
parent259abeacb4a7122cf6f27ab25e6da4e456053749 (diff)
cifuzz: Fix artifacts uploading issues. (#6646)
-rw-r--r--infra/cifuzz/fuzz_target.py78
-rw-r--r--infra/cifuzz/fuzz_target_test.py20
-rw-r--r--infra/cifuzz/run_fuzzers.py18
-rw-r--r--infra/cifuzz/run_fuzzers_test.py20
4 files changed, 71 insertions, 65 deletions
diff --git a/infra/cifuzz/fuzz_target.py b/infra/cifuzz/fuzz_target.py
index c42d160c..8c62a64a 100644
--- a/infra/cifuzz/fuzz_target.py
+++ b/infra/cifuzz/fuzz_target.py
@@ -17,12 +17,14 @@ import logging
import os
import shutil
import stat
+import tempfile
import clusterfuzz.environment
import clusterfuzz.fuzz
import config_utils
import logs
+import stack_parser
logs.init()
@@ -106,6 +108,24 @@ class FuzzTarget: # pylint: disable=too-many-instance-attributes
self.latest_corpus_path)
return self.latest_corpus_path
+ def _target_artifact_path(self):
+ """Target artifact path."""
+ artifact_path = os.path.join(self.workspace.artifacts, self.target_name,
+ self.config.sanitizer)
+ os.makedirs(artifact_path, exist_ok=True)
+ return artifact_path
+
+ def _save_crash(self, crash):
+ """Add stacktraces to crashes."""
+ target_reproducer_path = os.path.join(self._target_artifact_path(),
+ os.path.basename(crash.input_path))
+ shutil.copy(crash.input_path, target_reproducer_path)
+
+ bug_summary_artifact_path = target_reproducer_path + '.summary'
+ stack_parser.parse_fuzzer_output(crash.stacktrace,
+ bug_summary_artifact_path)
+ return target_reproducer_path
+
def prune(self):
"""Prunes the corpus and returns the result."""
self._download_corpus()
@@ -117,7 +137,7 @@ class FuzzTarget: # pylint: disable=too-many-instance-attributes
result = engine_impl.minimize_corpus(self.target_path, [],
[self.latest_corpus_path],
self.pruned_corpus_path,
- self.workspace.artifacts,
+ self._target_artifact_path(),
self.duration)
return FuzzResult(None, result.logs, self.pruned_corpus_path)
@@ -134,32 +154,36 @@ class FuzzTarget: # pylint: disable=too-many-instance-attributes
corpus_path = self.latest_corpus_path
logging.info('Starting fuzzing')
- with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE,
- self.config.sanitizer,
- self.target_path,
- interactive=True) as env:
- engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE)
- options = engine_impl.prepare(corpus_path, env.target_path, env.build_dir)
- options.merge_back_new_testcases = False
- options.analyze_dictionary = False
- options.arguments.extend(LIBFUZZER_OPTIONS)
-
- result = engine_impl.fuzz(self.target_path, options,
- self.workspace.artifacts, self.duration)
-
- # Libfuzzer timeout was reached.
- if not result.crashes:
- logging.info('Fuzzer %s finished with no crashes discovered.',
- self.target_name)
- return FuzzResult(None, None, self.latest_corpus_path)
-
- # Only report first crash.
- crash = result.crashes[0]
- logging.info('Fuzzer: %s. Detected bug.', self.target_name)
-
- if self.is_crash_reportable(crash.input_path):
- # We found a bug in the fuzz target and we will report it.
- return FuzzResult(crash.input_path, result.logs, self.latest_corpus_path)
+ with tempfile.TemporaryDirectory() as artifacts_dir:
+ with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE,
+ self.config.sanitizer,
+ self.target_path,
+ interactive=True) as env:
+ engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE)
+ options = engine_impl.prepare(corpus_path, env.target_path,
+ env.build_dir)
+ options.merge_back_new_testcases = False
+ options.analyze_dictionary = False
+ options.arguments.extend(LIBFUZZER_OPTIONS)
+
+ result = engine_impl.fuzz(self.target_path, options, artifacts_dir,
+ self.duration)
+
+ # Libfuzzer timeout was reached.
+ if not result.crashes:
+ logging.info('Fuzzer %s finished with no crashes discovered.',
+ self.target_name)
+ return FuzzResult(None, None, self.latest_corpus_path)
+
+ # Only report first crash.
+ crash = result.crashes[0]
+ logging.info('Fuzzer: %s. Detected bug:\n%s', self.target_name,
+ crash.stacktrace)
+
+ if self.is_crash_reportable(crash.input_path):
+ # We found a bug in the fuzz target and we will report it.
+ saved_path = self._save_crash(crash)
+ return FuzzResult(saved_path, result.logs, self.latest_corpus_path)
# We found a bug but we won't report it.
return FuzzResult(None, None, self.latest_corpus_path)
diff --git a/infra/cifuzz/fuzz_target_test.py b/infra/cifuzz/fuzz_target_test.py
index ecea6fbb..33d58a49 100644
--- a/infra/cifuzz/fuzz_target_test.py
+++ b/infra/cifuzz/fuzz_target_test.py
@@ -220,5 +220,25 @@ class IsCrashReportableTest(fake_filesystem_unittest.TestCase):
'introduced.')
+class FuzzTest(fake_filesystem_unittest.TestCase):
+ """Fuzz test."""
+
+ def setUp(self):
+ """Sets up example fuzz target to test is_reproducible method."""
+ self.setUpPyfakefs()
+ deployment = _create_deployment()
+ config = deployment.config
+ workspace = deployment.workspace
+ self.fuzz_target = fuzz_target.FuzzTarget('/path/fuzz-target', 10,
+ workspace, deployment, config)
+
+ def test_get_fuzz_target_artifact(self):
+ """Tests that get_fuzz_target_artifact works as intended."""
+ # pylint: disable=protected-access
+ fuzz_target_artifact = self.fuzz_target._target_artifact_path()
+ self.assertEqual('/workspace/out/artifacts/fuzz-target/address',
+ fuzz_target_artifact)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/infra/cifuzz/run_fuzzers.py b/infra/cifuzz/run_fuzzers.py
index f59ef4f8..ef468b9c 100644
--- a/infra/cifuzz/run_fuzzers.py
+++ b/infra/cifuzz/run_fuzzers.py
@@ -15,14 +15,12 @@
import enum
import logging
import os
-import shutil
import sys
import time
import clusterfuzz_deployment
import fuzz_target
import generate_coverage_report
-import stack_parser
import workspace_utils
# pylint: disable=wrong-import-position,import-error
@@ -106,13 +104,6 @@ class BaseFuzzTargetRunner:
bug is found."""
raise NotImplementedError('Child class must implement method.')
- def get_fuzz_target_artifact(self, target, artifact_name):
- """Returns the path of a fuzzing artifact named |artifact_name| for
- |fuzz_target|."""
- artifact_name = (f'{target.target_name}-{self.config.sanitizer}-'
- f'{artifact_name}')
- return os.path.join(self.workspace.artifacts, artifact_name)
-
def create_fuzz_target_obj(self, target_path, run_seconds):
"""Returns a fuzz target object."""
return fuzz_target.FuzzTarget(target_path, run_seconds, self.workspace,
@@ -149,15 +140,6 @@ class BaseFuzzTargetRunner:
target.target_name)
continue
- # TODO(metzman): Do this with filestore.
- testcase_artifact_path = self.get_fuzz_target_artifact(
- target, os.path.basename(result.testcase))
- shutil.move(result.testcase, testcase_artifact_path)
- bug_summary_artifact_path = self.get_fuzz_target_artifact(
- target, 'bug-summary.txt')
- stack_parser.parse_fuzzer_output(result.stacktrace,
- bug_summary_artifact_path)
-
bug_found = True
if self.quit_on_bug_found:
logging.info('Bug found. Stopping fuzzing.')
diff --git a/infra/cifuzz/run_fuzzers_test.py b/infra/cifuzz/run_fuzzers_test.py
index 1e561c2b..4f65a8bf 100644
--- a/infra/cifuzz/run_fuzzers_test.py
+++ b/infra/cifuzz/run_fuzzers_test.py
@@ -211,24 +211,6 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase):
out_path)
self._test_initialize_fail(expected_error_args, workspace=tmp_dir)
- def test_get_fuzz_target_artifact(self):
- """Tests that get_fuzz_target_artifact works as intended."""
- with tempfile.TemporaryDirectory() as tmp_dir:
- runner = self._create_runner(workspace=tmp_dir)
- crashes_dir = 'crashes-dir'
- runner.crashes_dir = crashes_dir
- artifact_name = 'artifact-name'
- target = mock.MagicMock()
- target_name = 'target_name'
- target.target_name = target_name
-
- fuzz_target_artifact = runner.get_fuzz_target_artifact(
- target, artifact_name)
- expected_fuzz_target_artifact = os.path.join(
- tmp_dir, 'out', 'artifacts', 'target_name-address-artifact-name')
-
- self.assertEqual(fuzz_target_artifact, expected_fuzz_target_artifact)
-
class CiFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase):
"""Tests that CiFuzzTargetRunner works as intended."""
@@ -264,8 +246,6 @@ class CiFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase):
magic_mock.target_name = 'target1'
mock_create_fuzz_target_obj.return_value = magic_mock
self.assertTrue(runner.run_fuzz_targets())
- self.assertIn('target1-address-testcase',
- os.listdir(runner.workspace.artifacts))
self.assertEqual(mock_run_fuzz_target.call_count, 1)