Пример #1
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)
Пример #2
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)
Пример #3
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],
    )
Пример #4
0
def _update_issue_metadata(testcase):
  """Update issue metadata."""
  if environment.is_trusted_host():
    # Not applicable.
    return

  if testcase.uploader_email:
    # Trust the uploader specified metadata.
    return

  fuzz_target = testcase.get_fuzz_target()
  if not fuzz_target:
    return

  build_dir = environment.get_value('BUILD_DIR')
  target_path = engine_common.find_fuzzer_path(build_dir, fuzz_target.binary)
  if not target_path:
    logs.log_error('Failed to find target path for ' + fuzz_target.binary)
    return

  metadata = engine_common.get_all_issue_metadata(target_path)
  for key, value in six.iteritems(metadata):
    old_value = testcase.get_metadata(key)
    if old_value != value:
      logs.log('Updating issue metadata for {} from {} to {}.'.format(
          key, old_value, value))
      testcase.set_metadata(key, value)
Пример #5
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)))
Пример #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=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)
Пример #7
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))
Пример #8
0
  def test_fuzz_no_crash(self):
    """Test fuzzing (no crash)."""
    _, corpus_path = setup_testcase_and_corpus('empty', 'corpus')
    engine_impl = engine.HonggfuzzEngine()
    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.assertListEqual([
        os.path.join(DATA_DIR, 'honggfuzz'),
        '-n',
        '1',
        '--exit_upon_crash',
        '-v',
        '-z',
        '-P',
        '-S',
        '--rlimit_rss',
        '2560',
        '--timeout',
        '25',
        '--dict',
        os.path.join(DATA_DIR, 'test_fuzzer.dict'),
        '--input',
        os.path.join(TEMP_DIR, 'corpus'),
        '--workspace',
        TEMP_DIR,
        '--run_time',
        '10',
        '--',
        target_path,
    ], results.command)

    self.assertGreater(len(os.listdir(corpus_path)), 0)
    self.assert_has_stats(results)
Пример #9
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)
Пример #10
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,
    )
Пример #11
0
def engine_reproduce(engine_impl, target_name, testcase_path, arguments,
                     timeout):
    """Do engine reproduction."""
    if environment.is_trusted_host():
        from bot.untrusted_runner import tasks_host
        return tasks_host.engine_reproduce(engine_impl, target_name,
                                           testcase_path, arguments, timeout)
    build_dir = environment.get_value('BUILD_DIR')
    is_blackbox = engine_impl.name == 'blackbox'
    target_path = engine_common.find_fuzzer_path(build_dir,
                                                 target_name,
                                                 is_blackbox=is_blackbox)
    if not target_path:
        raise TargetNotFoundError('Failed to find target ' + target_name)

    result = engine_impl.reproduce(target_path, testcase_path, list(arguments),
                                   timeout)

    # This matches the check in process_handler.run_process.
    if not result.return_code and \
        (crash_analyzer.is_memory_tool_crash(result.output) or
         crash_analyzer.is_check_failure_crash(result.output)):
        result.return_code = 1

    return result
Пример #12
0
    def __init__(self,
                 fuzzer_name,
                 testcase_path,
                 test_timeout,
                 gestures,
                 needs_http=False):
        self._testcase_path = testcase_path
        self._test_timeout = test_timeout
        self._gestures = gestures
        self._needs_http = needs_http

        engine_impl = engine.get(fuzzer_name)
        if engine_impl:
            self._is_black_box = False
            self._engine_impl = engine_impl

            # Read target_name + args from flags file.
            additional_command_line_flags = get_additional_command_line_flags(
                testcase_path)
            self._arguments = additional_command_line_flags.split()
            target_name = self._arguments.pop(0)

            build_dir = environment.get_value('BUILD_DIR')
            self._target_path = engine_common.find_fuzzer_path(
                build_dir, target_name)
            if not self._target_path:
                raise TargetNotFoundError('Failed to find target ' +
                                          target_name)
        else:
            self._is_black_box = True
            self._command = get_command_line_for_application(
                testcase_path, needs_http=needs_http)
Пример #13
0
    def __init__(self, build_directory, context):
        self.build_directory = build_directory
        self.context = context

        self.fuzzer_path = engine_common.find_fuzzer_path(
            self.build_directory, self.context.fuzz_target.binary)
        if not self.fuzzer_path:
            raise CorpusPruningException('Failed to get fuzzer path for %s.' %
                                         self.context.fuzz_target.binary)

        fuzz_inputs_disk = environment.get_value('FUZZ_INPUTS_DISK')
        self.runner = libfuzzer.get_runner(self.fuzzer_path,
                                           temp_dir=fuzz_inputs_disk)

        if context.use_minijail:
            self.runner.chroot.add_binding(
                minijail.ChrootBinding(self.context.initial_corpus_path,
                                       '/corpus', False))
            self.runner.chroot.add_binding(
                minijail.ChrootBinding(self.context.minimized_corpus_path,
                                       '/min', True))
            self.runner.chroot.add_binding(
                minijail.ChrootBinding(self.context.shared_corpus_path,
                                       '/shared', False))
            self.runner.chroot.add_binding(
                minijail.ChrootBinding(self.context.bad_units_path,
                                       '/bad_units', True))

        self.fuzzer_options = options.get_fuzz_target_options(self.fuzzer_path)
Пример #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_reproduce(self):
   """Tests reproducing a crash."""
   testcase_path, _ = setup_testcase_and_corpus('crash', 'empty_corpus')
   engine_impl = engine.HonggfuzzEngine()
   target_path = engine_common.find_fuzzer_path(DATA_DIR, 'test_fuzzer')
   result = engine_impl.reproduce(target_path, testcase_path, [], 65)
   self.assertListEqual([target_path], result.command)
   self.assertIn('ERROR: AddressSanitizer: heap-use-after-free', result.output)
Пример #16
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)
Пример #17
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))
Пример #18
0
    def __init__(self, build_directory, context):
        self.build_directory = build_directory
        self.context = context

        self.target_path = engine_common.find_fuzzer_path(
            self.build_directory, self.context.fuzz_target.binary)
        if not self.target_path:
            raise CorpusPruningException("Failed to get fuzzer path for %s." %
                                         self.context.fuzz_target.binary)

        self.fuzzer_options = options.get_fuzz_target_options(self.target_path)
Пример #19
0
def engine_reproduce(engine_impl, target_name, testcase_path, arguments,
                     timeout):
    """Do engine reproduction."""
    if environment.is_trusted_host():
        from bot.untrusted_runner import tasks_host
        return tasks_host.engine_reproduce(engine_impl, target_name,
                                           testcase_path, arguments, timeout)
    build_dir = environment.get_value('BUILD_DIR')
    target_path = engine_common.find_fuzzer_path(build_dir, target_name)
    if not target_path:
        raise TargetNotFoundError('Failed to find target ' + target_name)

    return engine_impl.reproduce(target_path, testcase_path, list(arguments),
                                 timeout)
Пример #20
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)
Пример #21
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))
Пример #22
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)
Пример #23
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))
Пример #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(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)
Пример #25
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,
    )
Пример #26
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)
Пример #27
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.ld_library_path,
            self.hwasan_options,
            self.device_path(target_path),
            '-max_len=100',
            '-timeout=25',
            '-rss_limit_mb=2048',
            '-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=2048',
            '-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)
Пример #28
0
    def test_fuzz_crash(self):
        """Test fuzzing that results in a crash."""
        _, corpus_path = setup_testcase_and_corpus("empty", "corpus")
        engine_impl = engine.HonggfuzzEngine()
        target_path = engine_common.find_fuzzer_path(DATA_DIR,
                                                     "always_crash_fuzzer")
        options = engine_impl.prepare(corpus_path, target_path, DATA_DIR)
        results = engine_impl.fuzz(target_path, options, TEMP_DIR, 10)
        self.assertListEqual(
            [
                os.path.join(DATA_DIR, "honggfuzz"),
                "-n",
                "1",
                "--exit_upon_crash",
                "-v",
                "-z",
                "-P",
                "-S",
                "--rlimit_rss",
                "2560",
                "--timeout",
                "25",
                "--input",
                os.path.join(TEMP_DIR, "corpus"),
                "--workspace",
                TEMP_DIR,
                "--run_time",
                "10",
                "--",
                target_path,
            ],
            results.command,
        )

        self.assertIn("Seen a crash. Terminating all fuzzing threads",
                      results.logs)
        self.assertEqual(1, len(results.crashes))
        crash = results.crashes[0]
        self.assertEqual(TEMP_DIR, os.path.dirname(crash.input_path))
        self.assertIn("ERROR: AddressSanitizer: heap-use-after-free",
                      crash.stacktrace)

        with open(crash.input_path) as f:
            self.assertEqual("A", f.read()[0])

        self.assert_has_stats(results)
Пример #29
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)
Пример #30
0
    def test_exit_target_bug_not_logged(self, exit_code):
        """Test that we don't log when exit code indicates bug found in target."""
        test_helpers.patch(self, [
            'metrics.logs.log_error',
        ])

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

        self.mock.log_error.side_effect = mocked_log_error
        _, corpus_path = setup_testcase_and_corpus('empty',
                                                   'corpus_with_some_files')
        os.environ['EXIT_FUZZER_CODE'] = exit_code

        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)