예제 #1
0
def move_mergeable_units(merge_directory, corpus_directory):
    """Move new units in |merge_directory| into |corpus_directory|."""
    initial_units = set(
        os.path.basename(filename)
        for filename in shell.get_files_list(corpus_directory))

    for unit_path in shell.get_files_list(merge_directory):
        unit_name = os.path.basename(unit_path)
        if unit_name in initial_units and is_sha1_hash(unit_name):
            continue
        dest_path = os.path.join(corpus_directory, unit_name)
        shell.move(unit_path, dest_path)
예제 #2
0
def legalize_corpus_files(directory):
    """Convert the name of every corpus file in |directory| to a name that is
  allowed on Windows."""
    # Iterate through return value of legalize_filenames to convert every
    # filename.
    files_list = shell.get_files_list(directory)
    legalize_filenames(files_list)
예제 #3
0
def find_mutator_plugin():
  """Sets LD_PRELOAD to the path of a usable mutator plugin shared object.
  This should only be called after a call to get_mutator_plugin."""
  paths = shell.get_files_list(_get_mutator_plugins_unpacked_dir())
  # This function should not be called unless there is an unpacked plugin.
  for path in paths:
    if os.path.basename(path) == MUTATOR_SHARED_OBJECT_FILENAME:
      return path
  return None
예제 #4
0
def generate_new_testcase_mutations_using_radamsa(
        corpus_directory, new_testcase_mutations_directory,
        generation_timeout):
    """Generate new testcase mutations based on Radamsa."""
    radamsa_path = get_radamsa_path()
    if not radamsa_path:
        # Mutations using radamsa are not supported on current platform, bail out.
        return

    radamsa_runner = new_process.ProcessRunner(radamsa_path)
    files_list = shell.get_files_list(corpus_directory)
    filtered_files_list = [
        f for f in files_list if os.path.getsize(f) <= CORPUS_INPUT_SIZE_LIMIT
    ]
    if not filtered_files_list:
        # No mutations to do on an empty corpus or one with very large files.
        return

    old_corpus_size = shell.get_directory_file_count(
        new_testcase_mutations_directory)
    expected_completion_time = time.time() + generation_timeout

    for i in range(RADAMSA_MUTATIONS):
        original_file_path = random_choice(filtered_files_list)
        original_filename = os.path.basename(original_file_path)
        output_path = os.path.join(
            new_testcase_mutations_directory,
            get_radamsa_output_filename(original_filename, i))

        result = radamsa_runner.run_and_wait(
            ['-o', output_path, original_file_path], timeout=RADAMSA_TIMEOUT)

        if (os.path.exists(output_path)
                and os.path.getsize(output_path) > CORPUS_INPUT_SIZE_LIMIT):
            # Skip large files to avoid furthur mutations and impact fuzzing
            # efficiency.
            shell.remove_file(output_path)
        elif result.return_code or result.timed_out:
            logs.log_warn('Radamsa failed to mutate or timed out.',
                          output=result.output)

        # Check if we exceeded our timeout. If yes, do no more mutations and break.
        if time.time() > expected_completion_time:
            break

    new_corpus_size = shell.get_directory_file_count(
        new_testcase_mutations_directory)
    logs.log('Added %d tests using Radamsa mutations.' %
             (new_corpus_size - old_corpus_size))
예제 #5
0
def unpack_seed_corpus_if_needed(
    fuzz_target_path,
    corpus_directory,
    max_bytes=float("inf"),
    force_unpack=False,
    max_files_for_unpack=MAX_FILES_FOR_UNPACK,
):
    """If seed corpus available, unpack it into the corpus directory if needed,
    ie: if corpus exists and either |force_unpack| is True, or the number of files
    in corpus_directory is less than |max_files_for_unpack|. Uses
    |fuzz_target_path| to find the seed corpus. If max_bytes is specified, then
    seed corpus files larger than |max_bytes| will not be unpacked.
    """
    seed_corpus_archive_path = get_seed_corpus_path(fuzz_target_path)
    if not seed_corpus_archive_path:
        return

    num_corpus_files = len(shell.get_files_list(corpus_directory))
    if not force_unpack and num_corpus_files > max_files_for_unpack:
        return

    if force_unpack:
        logs.log("Forced unpack: %s." % seed_corpus_archive_path)

    archive_iterator = archive.iterator(seed_corpus_archive_path)
    # Unpack seed corpus recursively into the root of the main corpus directory.
    idx = 0
    for seed_corpus_file in archive_iterator:
        # Ignore directories.
        if seed_corpus_file.name.endswith("/"):
            continue

        # Allow callers to opt-out of unpacking large files.
        if seed_corpus_file.size > max_bytes:
            continue

        output_filename = "%016d" % idx
        output_file_path = os.path.join(corpus_directory, output_filename)
        with open(output_file_path, "wb") as file_handle:
            shutil.copyfileobj(seed_corpus_file.handle, file_handle)

        idx += 1

    logs.log("Unarchiving %d files from seed corpus %s." %
             (idx, seed_corpus_archive_path))
예제 #6
0
def generate_new_testcase_mutations_using_radamsa(
        corpus_directory, new_testcase_mutations_directory,
        expected_completion_time):
    """Generate new testcase mutations based on Radamsa."""
    radamsa_path = get_radamsa_path()
    if not radamsa_path:
        # Mutations using radamsa are not supported on current platform, bail out.
        return

    radamsa_runner = new_process.ProcessRunner(radamsa_path)
    files_list = shell.get_files_list(corpus_directory)
    if not files_list:
        # No mutations to do on an empty corpus, bail out.
        return

    old_corpus_size = shell.get_directory_file_count(
        new_testcase_mutations_directory)

    for i in range(RADAMSA_MUTATIONS):
        original_file_path = engine_common.random_choice(files_list)
        original_filename = os.path.basename(original_file_path)
        output_path = os.path.join(
            new_testcase_mutations_directory,
            'radamsa-%08d-%s' % (i + 1, original_filename))

        result = radamsa_runner.run_and_wait(
            ['-o', output_path, original_file_path], timeout=RADAMSA_TIMEOUT)
        if result.return_code or result.timed_out:
            logs.log_error('Radamsa failed to mutate or timed out.',
                           output=result.output)

        # Check if we exceeded our timeout. If yes, do no more mutations and break.
        if time.time() > expected_completion_time:
            break

    new_corpus_size = shell.get_directory_file_count(
        new_testcase_mutations_directory)
    logs.log('Added %d tests using Radamsa mutations.' %
             (new_corpus_size - old_corpus_size))