def test_reproduce(self):
        """Test reproduce."""
        testcase_file_path = os.path.join(self.temp_dir, 'testcase')
        with open(testcase_file_path, 'wb') as f:
            f.write(b'EEE')

        self._setup_env(job_type='libfuzzer_asan_job')

        build_manager.setup_build()
        result = testcase_manager.engine_reproduce(
            libfuzzer_engine.LibFuzzerEngine(), 'test_fuzzer',
            testcase_file_path, [], 30)

        self.assertEqual([
            os.path.join(environment.get_value('BUILD_DIR'), 'test_fuzzer'),
            '-runs=100',
            file_host.rebase_to_worker_root(testcase_file_path)
        ], result.command)
        self.assertEqual(result.return_code,
                         libfuzzer_constants.TARGET_ERROR_EXITCODE)
        self.assertGreater(result.time_executed, 0)
        self.assertIn('Running 1 inputs 100 time(s) each', result.output)
        self.assertIn(
            'AddressSanitizer: SEGV on unknown address 0x000000000000',
            result.output)
示例#2
0
    def test_exit_failure_logged(self):
        """Test that we log when libFuzzer's exit code indicates it ran into an
    error."""
        test_helpers.patch(self, [
            'metrics.logs.log_error',
        ])

        def mocked_log_error(*args, **kwargs):  # pylint: disable=unused-argument
            self.assertIn(engine.ENGINE_ERROR_MESSAGE, args[0])

        self.mock.log_error.side_effect = mocked_log_error
        _, corpus_path = setup_testcase_and_corpus('empty',
                                                   'corpus_with_some_files')

        target_path = engine_common.find_fuzzer_path(DATA_DIR, 'exit_fuzzer')
        engine_impl = engine.LibFuzzerEngine()
        options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)
        options.extra_env['EXIT_FUZZER_CODE'] = '1'

        results = engine_impl.fuzz(target_path, options, TEMP_DIR, 10)
        self.assertEqual(1, self.mock.log_error.call_count)

        self.assertEqual(1, len(results.crashes))
        self.assertEqual(fuzzer_utils.get_temp_dir(),
                         os.path.dirname(results.crashes[0].input_path))
        self.assertEqual(0, os.path.getsize(results.crashes[0].input_path))
示例#3
0
  def test_fuzzer_can_boot_and_run_with_corpus(self):
    """Tests running a single round of fuzzing on a Fuchsia target, using
        a toy fuzzer that should crash very quickly.

        Additionally, tests that pushing a corpus to the target works & produces
        an expanded corpus."""
    environment.set_value("JOB_NAME", "libfuzzer_asan_fuchsia")
    environment.set_value("FUZZ_TARGET", "example_fuzzers/trap_fuzzer")
    build_manager.setup_build()

    _, corpus_path = setup_testcase_and_corpus("aaaa", "fuchsia_corpus")
    num_files_original = len([corpfile for corpfile in os.listdir(corpus_path)])
    engine_impl = engine.LibFuzzerEngine()

    self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(20.0)
    options = engine_impl.prepare(corpus_path, "example_fuzzers/trap_fuzzer",
                                  DATA_DIR)
    results = engine_impl.fuzz("example_fuzzers/trap_fuzzer", options, TEMP_DIR,
                               20)

    # If we don't get a crash, something went wrong.
    self.assertIn("Test unit written to", results.logs)
    # Check that the command was invoked with a corpus argument.
    self.assertIn("data/corpus/new", results.command)
    # Check that new units were added to the corpus.
    num_files_new = len([
        corpfile
        for corpfile in os.listdir(os.path.join(TEMP_DIR, "temp-1337/new"))
    ])
    self.assertGreater(num_files_new, num_files_original)
示例#4
0
  def test_prepare(self):
    """Test prepare."""
    engine_impl = engine.LibFuzzerEngine()
    options = engine_impl.prepare("/corpus_dir", "/path/target", "/path")
    self.assertEqual("/corpus_dir", options.corpus_dir)
    self.assertItemsEqual(
        [
            "-max_len=31337",
            "-timeout=11",
            "-rss_limit_mb=2560",
            "-arg1",
            "-dict=/path/blah.dict",
        ],
        options.arguments,
    )
    self.assertDictEqual({
        "value_profile": 1,
        "corpus_subset": 20,
        "fork": 2
    }, options.strategies)
    self.assertItemsEqual(["/new_corpus_dir", "/corpus_dir"],
                          options.fuzz_corpus_dirs)
    self.assertDictEqual({"extra_env": "1"}, options.extra_env)
    self.assertFalse(options.use_dataflow_tracing)
    self.assertTrue(options.is_mutations_run)

    self.mock.unpack_seed_corpus_if_needed.assert_called_with(
        "/path/target", "/corpus_dir")
示例#5
0
  def test_single_testcase_crash(self):
    """Tests libfuzzer with a crashing testcase."""
    testcase_path, _ = setup_testcase_and_corpus("crash", "empty_corpus")
    engine_impl = engine.LibFuzzerEngine()
    target_path = engine_common.find_fuzzer_path(ANDROID_DATA_DIR,
                                                 "test_fuzzer")
    result = engine_impl.reproduce(target_path, testcase_path,
                                   ["-timeout=60", "-rss_limit_mb=2560"], 65)

    self.assertEqual(
        [
            self.adb_path,
            "shell",
            self.hwasan_options,
            self.device_path(target_path),
            "-timeout=60",
            "-rss_limit_mb=2560",
            "-runs=100",
            self.device_path(testcase_path),
        ],
        result.command,
    )
    self.assertIn(
        "ERROR: HWAddressSanitizer: SEGV on unknown address 0x000000000000",
        result.output,
    )
示例#6
0
  def test_fuzz_from_subset(self):
    """Tests fuzzing from corpus subset."""
    self.mock.generate_weighted_strategy_pool.return_value = set_strategy_pool(
        [strategy.CORPUS_SUBSET_STRATEGY])
    self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(5.0)

    _, corpus_path = setup_testcase_and_corpus("empty",
                                               "corpus_with_some_files")

    engine_impl = engine.LibFuzzerEngine()
    target_path = engine_common.find_fuzzer_path(DATA_DIR, "test_fuzzer")
    dict_path = target_path + ".dict"
    options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)
    results = engine_impl.fuzz(target_path, options, TEMP_DIR, 10)

    self.compare_arguments(
        os.path.join(DATA_DIR, "test_fuzzer"),
        [
            "-max_len=256",
            "-timeout=25",
            "-rss_limit_mb=2560",
            "-dict=" + dict_path,
            "-artifact_prefix=" + TEMP_DIR + "/",
            "-max_total_time=5",
            "-print_final_stats=1",
        ],
        [
            os.path.join(TEMP_DIR, "temp-1337/new"),
            os.path.join(TEMP_DIR, "temp-1337/subset"),
        ],
        results.command,
    )

    self.assert_has_stats(results.stats)
示例#7
0
    def test_fuzz_no_crash(self):
        """Tests fuzzing (no crash)."""
        self.mock.generate_weighted_strategy_pool.return_value = set_strategy_pool(
            [strategy.VALUE_PROFILE_STRATEGY])

        self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(5.0)
        _, corpus_path = setup_testcase_and_corpus('empty', 'corpus')
        engine_impl = engine.LibFuzzerEngine()

        target_path = engine_common.find_fuzzer_path(DATA_DIR, 'test_fuzzer')
        options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)

        results = engine_impl.fuzz(target_path, options, TEMP_DIR, 10)

        self.assert_has_stats(results.stats)
        self.compare_arguments(os.path.join(DATA_DIR, 'test_fuzzer'), [
            '-max_len=256', '-timeout=25', '-rss_limit_mb=2048',
            '-use_value_profile=1', '-artifact_prefix=' + TEMP_DIR + '/',
            '-max_total_time=5', '-print_final_stats=1'
        ], [
            os.path.join(TEMP_DIR, 'temp-1337/new'),
            os.path.join(TEMP_DIR, 'corpus')
        ], results.command)
        self.assertEqual(0, len(results.crashes))

        # New items should've been added to the corpus.
        self.assertNotEqual(0, len(os.listdir(corpus_path)))
示例#8
0
  def test_qemu_logs_returned_on_error(self):
    """Test running against a qemu that has died"""
    test_helpers.patch(self, ["metrics.logs.log_warn"])
    # Pass-through logs just so we can see what's going on (but moving from
    # log_warn to plain log to avoid creating a loop)
    self.mock.log_warn.side_effect = logs.log

    environment.set_value("FUZZ_TARGET", "example_fuzzers/overflow_fuzzer")
    environment.set_value("JOB_NAME", "libfuzzer_asan_fuchsia")
    build_manager.setup_build()
    testcase_path, _ = setup_testcase_and_corpus("fuchsia_crash",
                                                 "empty_corpus")

    runner = libfuzzer.FuchsiaQemuLibFuzzerRunner("fake/fuzzer")
    # Check that it's up properly
    self.assertEqual(runner.device.ssh(["echo", "hello"]), 0)
    # Force shutdown
    runner.device.ssh(["dm", "shutdown"])

    # Try to fuzz against the dead qemu to trigger automatic recovery behavior
    engine_impl = engine.LibFuzzerEngine()
    engine_impl.reproduce(
        "example_fuzzers/overflow_fuzzer",
        testcase_path,
        ["-timeout=25", "-rss_limit_mb=2560"],
        30,
    )

    # Check the logs for the shutdown sequence
    self.assertIn("Shutting down", self.mock.log_warn.call_args[0][0])
示例#9
0
    def test_qemu_logs_returned_on_error(self):
        """Test running against a qemu that has died"""
        test_helpers.patch(self, ['metrics.logs.log_warn'])
        # Pass-through logs just so we can see what's going on (but moving from
        # log_warn to plain log to avoid creating a loop)
        self.mock.log_warn.side_effect = logs.log

        environment.set_value('FUZZ_TARGET', 'example_fuzzers/overflow_fuzzer')
        environment.set_value('JOB_NAME', 'libfuzzer_asan_fuchsia')
        build_manager.setup_build()
        testcase_path, _ = setup_testcase_and_corpus('fuchsia_crash',
                                                     'empty_corpus')

        runner = libfuzzer.FuchsiaQemuLibFuzzerRunner('fake/fuzzer')
        # Check that it's up properly
        self.assertEqual(runner.device.ssh(['echo', 'hello']), 0)
        # Force shutdown
        runner.device.ssh(['dm', 'shutdown'])

        # Try to fuzz against the dead qemu to trigger automatic recovery behavior
        engine_impl = engine.LibFuzzerEngine()
        engine_impl.reproduce('example_fuzzers/overflow_fuzzer', testcase_path,
                              ['-timeout=25', '-rss_limit_mb=2048'], 30)

        # Check the logs for the shutdown sequence
        self.assertIn('Shutting down', self.mock.log_warn.call_args[0][0])
示例#10
0
    def test_fuzz_from_subset(self):
        """Tests fuzzing from corpus subset."""
        self.mock.generate_weighted_strategy_pool.return_value = set_strategy_pool(
            [strategy.CORPUS_SUBSET_STRATEGY])
        self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(5.0)

        _, corpus_path = setup_testcase_and_corpus('empty',
                                                   'corpus_with_some_files')

        engine_impl = engine.LibFuzzerEngine()
        target_path = engine_common.find_fuzzer_path(DATA_DIR, 'test_fuzzer')
        dict_path = target_path + '.dict'
        options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)
        results = engine_impl.fuzz(target_path, options, TEMP_DIR, 10)

        self.compare_arguments(os.path.join(DATA_DIR, 'test_fuzzer'), [
            '-max_len=256', '-timeout=25', '-rss_limit_mb=2048',
            '-dict=' + dict_path, '-artifact_prefix=' + TEMP_DIR + '/',
            '-max_total_time=5', '-print_final_stats=1'
        ], [
            os.path.join(TEMP_DIR, 'temp-1337/new'),
            os.path.join(TEMP_DIR, 'temp-1337/subset')
        ], results.command)

        self.assert_has_stats(results.stats)
示例#11
0
  def test_analyze_dict(self):
    """Tests recommended dictionary analysis."""
    test_helpers.patch(
        self,
        [
            "bot.fuzzers.dictionary_manager.DictionaryManager."
            "parse_recommended_dictionary_from_log_lines",
            "bot.fuzzers.dictionary_manager.DictionaryManager."
            "update_recommended_dictionary",
        ],
    )

    self.mock.parse_recommended_dictionary_from_log_lines.return_value = {'"USELESS_0"',
        '"APPLE"',
        '"USELESS_1"',
        '"GINGER"',
        '"USELESS_2"',
        '"BEET"',
        '"USELESS_3"',}
    self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(5.0)

    _, corpus_path = setup_testcase_and_corpus("empty",
                                               "corpus_with_some_files")

    engine_impl = engine.LibFuzzerEngine()
    target_path = engine_common.find_fuzzer_path(DATA_DIR,
                                                 "analyze_dict_fuzzer")
    options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)
    engine_impl.fuzz(target_path, options, TEMP_DIR, 10)
    expected_recommended_dictionary = {'"APPLE"', '"GINGER"', '"BEET"'}

    self.assertIn(
        expected_recommended_dictionary,
        self.mock.update_recommended_dictionary.call_args[0],
    )
示例#12
0
  def test_fuzz_with_mutator_plugin(self):
    """Tests fuzzing with a mutator plugin."""
    self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(5.0)

    os.environ["MUTATOR_PLUGINS_DIR"] = os.path.join(TEMP_DIR,
                                                     "mutator-plugins")
    # TODO(metzman): Remove the old binary and switch the test to the new one.
    fuzz_target_name = "test_fuzzer_old"
    plugin_archive_name = "custom_mutator_plugin-libfuzzer_asan-test_fuzzer_old.zip"

    # Call before setting up the plugin since this call will erase the directory
    # the plugin is written to.
    _, corpus_path = setup_testcase_and_corpus("empty", "empty_corpus")
    plugin_archive_path = os.path.join(DATA_DIR, plugin_archive_name)

    self.mock.generate_weighted_strategy_pool.return_value = set_strategy_pool(
        [strategy.MUTATOR_PLUGIN_STRATEGY])
    self.mock._get_mutator_plugins_from_bucket.return_value = [  # pylint: disable=protected-access
        plugin_archive_name
    ]
    self.mock._download_mutator_plugin_archive.return_value = (  # pylint: disable=protected-access
        plugin_archive_path)
    custom_mutator_print_string = "CUSTOM MUTATOR\n"
    try:
      target_path = engine_common.find_fuzzer_path(DATA_DIR, fuzz_target_name)
      engine_impl = engine.LibFuzzerEngine()
      options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)
      results = engine_impl.fuzz(target_path, options, TEMP_DIR, 10)
    finally:
      shutil.rmtree(os.environ["MUTATOR_PLUGINS_DIR"])

    # custom_mutator_print_string gets printed before the custom mutator mutates
    # a test case. Assert that the count is greater than 1 to ensure that the
    # function didn't crash on its first execution (after printing).
    self.assertGreater(results.logs.count(custom_mutator_print_string), 1)
示例#13
0
    def test_fuzz_from_subset(self):
        """Tests fuzzing from corpus subset."""
        self.mock.generate_weighted_strategy_pool.return_value = set_strategy_pool(
            [strategy.CORPUS_SUBSET_STRATEGY])
        self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(5.0)

        _, corpus_path = setup_testcase_and_corpus('empty',
                                                   'corpus_with_some_files')

        engine_impl = engine.LibFuzzerEngine()
        target_path = engine_common.find_fuzzer_path(ANDROID_DATA_DIR,
                                                     'test_fuzzer')
        dict_path = target_path + '.dict'
        options = engine_impl.prepare(corpus_path, target_path,
                                      ANDROID_DATA_DIR)
        results = engine_impl.fuzz(target_path, options, TEMP_DIR, 10)

        self.assertEqual([
            self.adb_path,
            'shell',
            self.hwasan_options,
            self.device_path(target_path),
            '-max_len=256',
            '-timeout=25',
            '-rss_limit_mb=2048',
            '-dict=' + self.device_path(dict_path),
            '-artifact_prefix=' + self.device_path(TEMP_DIR) + '/',
            '-max_total_time=5',
            '-print_final_stats=1',
            self.device_path(os.path.join(TEMP_DIR, 'temp-1337/new')),
            self.device_path(os.path.join(TEMP_DIR, 'temp-1337/subset')),
        ], results.command)
        self.assertTrue(android.adb.file_exists(self.device_path(dict_path)))
        self.assert_has_stats(results.stats)
示例#14
0
    def test_merge_reductions(self):
        """Tests that reduced testcases are merged back into the original corpus
    without deleting the larger version."""
        self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(1.0)

        _, corpus_path = setup_testcase_and_corpus('empty', 'empty_corpus')
        fuzz_target_name = 'analyze_dict_fuzzer'

        test_helpers.patch(self, [
            'bot.fuzzers.libFuzzer.engine.LibFuzzerEngine._create_merge_corpus_dir',
            'system.shell.get_directory_file_count',
        ])

        self.mock.get_directory_file_count.side_effect = (
            mock_get_directory_file_count)

        minimal_unit_contents = 'APPLE'
        minimal_unit_hash = '569bea285d70dda2218f89ef5454ea69fb5111ef'
        nonminimal_unit_contents = 'APPLEO'
        nonminimal_unit_hash = '540d9ba6239483d60cd7448a3202b96c90409186'

        def mocked_create_merge_directory(_):
            """A mocked version of create_merge_directory that adds some interesting
      files to the merge corpus and initial corpus."""
            merge_directory_path = launcher.create_corpus_directory(
                'merge-corpus')
            shell.create_directory(merge_directory_path,
                                   create_intermediates=True,
                                   recreate=True)

            # Write the minimal unit to the merge directory.
            minimal_unit_path = os.path.join(merge_directory_path,
                                             minimal_unit_hash)
            with open(minimal_unit_path, 'w+') as file_handle:
                file_handle.write(minimal_unit_contents)

            # Write the nonminimal unit to the corpus directory.
            nonminimal_unit_path = os.path.join(corpus_path,
                                                nonminimal_unit_hash)
            with open(nonminimal_unit_path, 'w+') as file_handle:
                file_handle.write(nonminimal_unit_contents)

            return merge_directory_path

        # pylint: disable=protected-access
        self.mock._create_merge_corpus_dir.side_effect = (
            mocked_create_merge_directory)

        target_path = engine_common.find_fuzzer_path(DATA_DIR,
                                                     fuzz_target_name)
        engine_impl = engine.LibFuzzerEngine()
        options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)
        options.arguments.append('-runs=10')
        engine_impl.fuzz(target_path, options, TEMP_DIR, 10)

        # Verify that both the newly found minimal testcase and the nonminimal
        # testcase are in the corpus.
        self.assertIn(minimal_unit_hash, os.listdir(corpus_path))
        self.assertIn(nonminimal_unit_hash, os.listdir(corpus_path))
示例#15
0
 def test_single_testcase_crash(self):
     """Tests launcher with a crashing testcase."""
     testcase_path, _ = setup_testcase_and_corpus('crash', 'empty_corpus')
     engine_impl = engine.LibFuzzerEngine()
     target_path = engine_common.find_fuzzer_path(DATA_DIR, 'test_fuzzer')
     result = engine_impl.reproduce(target_path, testcase_path, [], 30)
     self.assertIn(
         'ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000',
         result.output)
示例#16
0
  def test_merge_reductions(self):
    """Tests that reduced testcases are merged back into the original corpus
        without deleting the larger version."""
    self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(1.0)

    _, corpus_path = setup_testcase_and_corpus("empty", "empty_corpus")
    fuzz_target_name = "analyze_dict_fuzzer"

    test_helpers.patch(
        self,
        [
            "bot.fuzzers.libFuzzer.engine.LibFuzzerEngine._create_merge_corpus_dir",
            "system.shell.get_directory_file_count",
        ],
    )

    self.mock.get_directory_file_count.side_effect = mock_get_directory_file_count

    minimal_unit_contents = "APPLE"
    minimal_unit_hash = "569bea285d70dda2218f89ef5454ea69fb5111ef"
    nonminimal_unit_contents = "APPLEO"
    nonminimal_unit_hash = "07aef0e305db0779f3b52ab4dad975a1b737c461"

    def mocked_create_merge_directory(_):
      """A mocked version of create_merge_directory that adds some interesting
            files to the merge corpus and initial corpus."""
      merge_directory_path = libfuzzer.create_corpus_directory("merge-corpus")

      # Write the minimal unit to the new corpus directory.
      new_corpus_directory_path = libfuzzer.create_corpus_directory("new")
      minimal_unit_path = os.path.join(new_corpus_directory_path,
                                       minimal_unit_hash)

      with open(minimal_unit_path, "w+") as file_handle:
        file_handle.write(minimal_unit_contents)

      # Write the nonminimal unit to the corpus directory.
      nonminimal_unit_path = os.path.join(corpus_path, nonminimal_unit_hash)
      with open(nonminimal_unit_path, "w+") as file_handle:
        file_handle.write(nonminimal_unit_contents)

      return merge_directory_path

    # pylint: disable=protected-access
    self.mock._create_merge_corpus_dir.side_effect = mocked_create_merge_directory

    target_path = engine_common.find_fuzzer_path(DATA_DIR, fuzz_target_name)
    engine_impl = engine.LibFuzzerEngine()
    options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)
    options.arguments.append("-runs=10")
    engine_impl.fuzz(target_path, options, TEMP_DIR, 10)

    # Verify that both the newly found minimal testcase and the nonminimal
    # testcase are in the corpus.
    self.assertIn(minimal_unit_hash, os.listdir(corpus_path))
    self.assertIn(nonminimal_unit_hash, os.listdir(corpus_path))
示例#17
0
    def test_prepare_auto_add_dict(self):
        """Test prepare automatically adding dict argument."""
        with open('/path/target.options', 'w') as f:
            f.write('[libfuzzer]\n' 'max_len=31337\n' 'timeout=11\n')
        self.fs.create_file('/path/target.dict')

        engine_impl = engine.LibFuzzerEngine()
        options = engine_impl.prepare('/corpus_dir', '/path/target', '/path')
        self.assertItemsEqual([
            '-max_len=31337', '-timeout=11', '-rss_limit_mb=2048', '-arg1',
            '-dict=/path/target.dict'
        ], options.arguments)
示例#18
0
  def test_fuzzer_can_boot_and_run_reproducer(self):
    """Tests running a testcase that should cause a fast, predictable crash."""
    build_manager.setup_fuchsia_build()
    testcase_path, _ = setup_testcase_and_corpus('fuchsia_crash',
                                                 'empty_corpus')
    engine_impl = engine.LibFuzzerEngine()
    result = engine_impl.reproduce('example_fuzzers/toy_fuzzer', testcase_path,
                                   ['-timeout=25', '-rss_limit_mb=2048'], 30)

    self.assertIn('ERROR: AddressSanitizer: heap-buffer-overflow on address',
                  result.output)
    self.assertIn('Running: data/fuchsia_crash', result.output)
    def test_target_not_found(self):
        """Test target not found."""
        testcase_file_path = os.path.join(self.temp_dir, 'testcase')
        with open(testcase_file_path, 'wb') as f:
            f.write(b'EEE')

        self._setup_env(job_type='libfuzzer_asan_job')

        build_manager.setup_build()
        with self.assertRaises(testcase_manager.TargetNotFoundError):
            testcase_manager.engine_reproduce(
                libfuzzer_engine.LibFuzzerEngine(), 'does_not_exist',
                testcase_file_path, [], 30)
示例#20
0
    def test_prepare_invalid_dict(self):
        """Test prepare with an invalid dict path."""
        with open('/path/target.options', 'w') as f:
            f.write('[libfuzzer]\n'
                    'max_len=31337\n'
                    'timeout=11\n'
                    'dict=not_exist.dict\n')

        engine_impl = engine.LibFuzzerEngine()
        options = engine_impl.prepare('/corpus_dir', '/path/target', '/path')
        self.assertItemsEqual(
            ['-max_len=31337', '-timeout=11', '-rss_limit_mb=2048', '-arg1'],
            options.arguments)
示例#21
0
 def test_single_testcase_crash(self):
   """Tests libfuzzer with a crashing testcase."""
   testcase_path, _ = setup_testcase_and_corpus('crash', 'empty_corpus')
   engine_impl = engine.LibFuzzerEngine()
   target_path = engine_common.find_fuzzer_path(DATA_DIR, 'test_fuzzer')
   result = engine_impl.reproduce(target_path, testcase_path,
                                  ['-timeout=60', '-rss_limit_mb=2560'], 65)
   self.compare_arguments(
       os.path.join(DATA_DIR, 'test_fuzzer'),
       ['-timeout=60', '-rss_limit_mb=2560', '-runs=100'], [testcase_path],
       result.command)
   self.assertIn(
       'ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000',
       result.output)
示例#22
0
  def test_prepare_invalid_dict(self):
    """Test prepare with an invalid dict path."""
    with open("/path/target.options", "w") as f:
      f.write("[libfuzzer]\n"
              "max_len=31337\n"
              "timeout=11\n"
              "dict=not_exist.dict\n")

    engine_impl = engine.LibFuzzerEngine()
    options = engine_impl.prepare("/corpus_dir", "/path/target", "/path")
    self.assertItemsEqual(
        ["-max_len=31337", "-timeout=11", "-rss_limit_mb=2560", "-arg1"],
        options.arguments,
    )
示例#23
0
  def test_fuzzer_can_boot_and_run_reproducer(self):
    """Tests running a testcase that should cause a fast, predictable crash."""
    environment.set_value('FUZZ_TARGET', 'example-fuzzers/overflow_fuzzer')
    environment.set_value('JOB_NAME', 'libfuzzer_asan_fuchsia')
    build_manager.setup_build()
    testcase_path, _ = setup_testcase_and_corpus('fuchsia_crash',
                                                 'empty_corpus')
    engine_impl = engine.LibFuzzerEngine()
    result = engine_impl.reproduce('example-fuzzers/overflow_fuzzer',
                                   testcase_path,
                                   ['-timeout=25', '-rss_limit_mb=2560'], 30)

    self.assertIn('ERROR: AddressSanitizer: heap-buffer-overflow on address',
                  result.output)
    self.assertIn('Running: data/fuchsia_crash', result.output)
示例#24
0
    def test_minimize(self):
        """Tests minimize."""
        testcase_path, _ = setup_testcase_and_corpus('aaaa', 'empty_corpus')
        minimize_output_path = os.path.join(TEMP_DIR, 'minimized_testcase')

        engine_impl = engine.LibFuzzerEngine()
        target_path = engine_common.find_fuzzer_path(ANDROID_DATA_DIR,
                                                     'crash_with_A_fuzzer')
        result = engine_impl.minimize_testcase(target_path, [], testcase_path,
                                               minimize_output_path, 30)
        self.assertTrue(result)
        self.assertTrue(os.path.exists(minimize_output_path))
        with open(minimize_output_path) as f:
            result = f.read()
            self.assertEqual('A', result)
示例#25
0
    def test_cleanse(self):
        """Tests cleanse."""
        testcase_path, _ = setup_testcase_and_corpus('aaaa', 'empty_corpus')
        cleanse_output_path = os.path.join(TEMP_DIR, 'cleansed_testcase')

        engine_impl = engine.LibFuzzerEngine()
        target_path = engine_common.find_fuzzer_path(ANDROID_DATA_DIR,
                                                     'crash_with_A_fuzzer')
        result = engine_impl.cleanse(target_path, [], testcase_path,
                                     cleanse_output_path, 30)
        self.assertTrue(result)
        self.assertTrue(os.path.exists(cleanse_output_path))
        with open(cleanse_output_path) as f:
            result = f.read()
            self.assertFalse(all(c == 'A' for c in result))
示例#26
0
  def test_cleanse(self):
    """Tests cleanse."""
    testcase_path, _ = setup_testcase_and_corpus("aaaa", "empty_corpus")
    cleanse_output_path = os.path.join(TEMP_DIR, "cleansed_testcase")

    engine_impl = engine.LibFuzzerEngine()
    target_path = engine_common.find_fuzzer_path(DATA_DIR,
                                                 "crash_with_A_fuzzer")
    result = engine_impl.cleanse(target_path, [], testcase_path,
                                 cleanse_output_path, 120)
    self.assertTrue(result)
    self.assertTrue(os.path.exists(cleanse_output_path))
    with open(cleanse_output_path) as f:
      result = f.read()
      self.assertFalse(all(c == "A" for c in result))
示例#27
0
  def test_minimize(self):
    """Tests minimize."""
    testcase_path, _ = setup_testcase_and_corpus("aaaa", "empty_corpus")
    minimize_output_path = os.path.join(TEMP_DIR, "minimized_testcase")

    engine_impl = engine.LibFuzzerEngine()
    target_path = engine_common.find_fuzzer_path(DATA_DIR,
                                                 "crash_with_A_fuzzer")
    result = engine_impl.minimize_testcase(target_path, [], testcase_path,
                                           minimize_output_path, 120)
    self.assertTrue(result)
    self.assertTrue(os.path.exists(minimize_output_path))
    with open(minimize_output_path) as f:
      result = f.read()
      self.assertEqual("A", result)
示例#28
0
  def test_fuzz_crash(self):
    """Tests fuzzing (crash)."""
    self.mock.get_fuzz_timeout.return_value = get_fuzz_timeout(5.0)
    _, corpus_path = setup_testcase_and_corpus("empty", "corpus")
    engine_impl = engine.LibFuzzerEngine()

    target_path = engine_common.find_fuzzer_path(ANDROID_DATA_DIR,
                                                 "always_crash_fuzzer")
    options = engine_impl.prepare(corpus_path, target_path, ANDROID_DATA_DIR)

    results = engine_impl.fuzz(target_path, options, TEMP_DIR, 10)

    self.assert_has_stats(results.stats)
    self.assertEqual(
        [
            self.adb_path,
            "shell",
            self.hwasan_options,
            self.device_path(target_path),
            "-max_len=100",
            "-timeout=25",
            "-rss_limit_mb=2560",
            "-artifact_prefix=" + self.device_path(TEMP_DIR) + "/",
            "-max_total_time=5",
            "-print_final_stats=1",
            self.device_path(os.path.join(TEMP_DIR, "temp-1337/new")),
            self.device_path(os.path.join(TEMP_DIR, "corpus")),
        ],
        results.command,
    )
    self.assertEqual(1, len(results.crashes))

    self.assertTrue(os.path.exists(results.crashes[0].input_path))
    self.assertEqual(TEMP_DIR, os.path.dirname(results.crashes[0].input_path))
    self.assertEqual(results.logs, results.crashes[0].stacktrace)
    self.assertListEqual(["-rss_limit_mb=2560", "-timeout=60"],
                         results.crashes[0].reproduce_args)

    self.assertIn(
        "Test unit written to {0}/crash-".format(
            self.device_path(self.crash_dir)),
        results.logs,
    )
    self.assertIn(
        "ERROR: HWAddressSanitizer: SEGV on unknown address "
        "0x000000000000",
        results.logs,
    )
示例#29
0
  def test_reproduce(self):
    """Test reproduce."""
    testcase_file_path = os.path.join(self.temp_dir, 'testcase')
    with open(testcase_file_path, 'wb') as f:
      f.write('EEE')

    self._setup_env(job_type='libfuzzer_asan_job')

    build_manager.setup_build()
    result = testcase_manager.engine_reproduce(
        libfuzzer_engine.LibFuzzerEngine(), 'test_fuzzer', testcase_file_path,
        [], 30)

    self.assertIn('Running 1 inputs 100 time(s) each', result.output)
    self.assertIn('AddressSanitizer: SEGV on unknown address 0x000000000000',
                  result.output)
示例#30
0
    def test_exit_failure_logged(self):
        """Test that we log when libFuzzer's exit code indicates it ran into an
    error."""
        test_helpers.patch(self, [
            'metrics.logs.log_error',
        ])

        _, corpus_path = setup_testcase_and_corpus('empty',
                                                   'corpus_with_some_files')
        os.environ['EXIT_FUZZER_CODE'] = '1'

        target_path = engine_common.find_fuzzer_path(DATA_DIR, 'exit_fuzzer')
        engine_impl = engine.LibFuzzerEngine()
        options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)
        engine_impl.fuzz(target_path, options, TEMP_DIR, 10)
        self.assertEqual(1, self.mock.log_error.call_count)