mirror of https://github.com/google/oss-fuzz.git
cifuzz: Fix artifacts uploading issues. (#6646)
This commit is contained in:
parent
259abeacb4
commit
f460c03c8a
|
@ -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)
|
||||
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,
|
||||
self.workspace.artifacts, self.duration)
|
||||
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)
|
||||
# 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)
|
||||
# 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.
|
||||
return FuzzResult(crash.input_path, result.logs, self.latest_corpus_path)
|
||||
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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.')
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue