def _fake_get_libfuzzer_testcase(*_):
    """Fake test case output intended to run "echo -n"."""
    testcase_map = {
        'crash_state': 'state',
        'security_flag': False,
        'gestures': [],
        'flaky_stack': False,
        'job_type': 'test_job',
        'redzone': 32,
        'additional_metadata': '{}',
        'fuzzer_name': 'libFuzzer',
        'job_definition': 'APP_NAME = launcher.py\n',
        'overridden_fuzzer_name': 'libFuzzer_test_fuzzer',
        'platform': environment.platform().lower(),
        'minimized_arguments': '',
        'window_argument': '',
        'timeout_multiplier': 1.0,
        'serialized_fuzz_target': {
            'binary': 'test_fuzzer',
            'engine': 'libFuzzer',
            'project': 'test_project',
        },
        'one_time_crasher_flag': False,
    }

    return reproduce.SerializedTestcase(testcase_map)
Example #2
0
def get_command_and_arguments(command_line):
    if environment.platform() == 'WINDOWS':
        command = command_line
    else:
        command = shlex.split(command_line, posix=True)

    return command, None
Example #3
0
def set_initial_testcase_metadata(testcase):
  """Set various testcase metadata fields during testcase initialization."""
  build_key = environment.get_value('BUILD_KEY')
  if build_key:
    testcase.set_metadata('build_key', build_key, update_testcase=False)

  build_url = environment.get_value('BUILD_URL')
  if build_url:
    testcase.set_metadata('build_url', build_url, update_testcase=False)

  gn_args_path = environment.get_value('GN_ARGS_PATH', '')
  if gn_args_path and os.path.exists(gn_args_path):
    gn_args = utils.read_data_from_file(
        gn_args_path, eval_data=False, default='')

    # Remove goma_dir from gn args since it is only relevant to the machine that
    # did the build.
    filtered_gn_args_lines = [
        line for line in gn_args.splitlines()
        if not GOMA_DIR_LINE_REGEX.match(line)
    ]
    filtered_gn_args = '\n'.join(filtered_gn_args_lines)
    testcase.set_metadata('gn_args', filtered_gn_args, update_testcase=False)

  testcase.platform = environment.platform().lower()
  testcase.platform_id = environment.get_platform_id()
Example #4
0
def find_fuzzer_path(build_directory, fuzzer_name):
    """Find the fuzzer path with the given name."""
    if not build_directory:
        # Grey-box fuzzers might not have the build directory for a particular job
        # configuration when doing variant task testing (e.g. Android on-device
        # fuzz target might not exist on host). In this case, treat it similar to
        # target not found by returning None.
        logs.log_warn('No build directory found for fuzzer: %s' % fuzzer_name)
        return None

    if environment.platform() == 'FUCHSIA':
        # Fuchsia targets are not on disk.
        return fuzzer_name

    # TODO(ochang): This is necessary for legacy testcases, which include the
    # project prefix in arguments. Remove this in the near future.
    project_name = environment.get_value('PROJECT_NAME')
    legacy_name_prefix = ''
    if project_name:
        legacy_name_prefix = project_name + '_'

    fuzzer_filename = environment.get_executable_filename(fuzzer_name)
    for root, _, files in os.walk(build_directory):
        for filename in files:
            if (legacy_name_prefix + filename == fuzzer_name
                    or filename == fuzzer_filename):
                return os.path.join(root, filename)

    # This is an expected case when doing regression testing with old builds
    # that do not have that fuzz target. It can also happen when a host sends a
    # message to an untrusted worker that just restarted and lost information on
    # build directory.
    logs.log_warn('Fuzzer: %s not found in build_directory: %s.' %
                  (fuzzer_name, build_directory))
    return None
Example #5
0
def is_check_failure_crash(stacktrace):
    """Return true if it a CHECK failure crash."""
    # Android-specific exception patterns.
    if environment.platform() == 'ANDROID':
        if 'Device rebooted' in stacktrace:
            return True
        if 'JNI DETECTED ERROR IN APPLICATION:' in stacktrace:
            return True
        if re.match(r'.*FATAL EXCEPTION.*:', stacktrace, re.DOTALL):
            return True

        # FIXME: Analyze why this is not working with chrome.
        # If the process has died, it is worthwhile to catch this with even a
        # NULL stack.
        # process_died_regex = (r'.*Process %s.*\(pid [0-9]+\) has died' %
        #                       environment.get_value('PKG_NAME'))
        # if re.match(process_died_regex, stacktrace, re.DOTALL):
        #   return True

        # Application CHECK failure known patterns.
    if re.match(r'.*#\s*Fatal error in', stacktrace, re.DOTALL):
        return True
    if 'Check failed:' in stacktrace:
        return True

    # Memory debugging tool CHECK failure.
    if 'Sanitizer CHECK failed:' in stacktrace:
        return True

    return False
Example #6
0
def restart_machine():
    """Restart machine."""
    if environment.platform() == 'WINDOWS':
        os.system('shutdown /f /r /t 0')
    else:
        # POSIX platforms.
        os.system('sudo shutdown -r now')
Example #7
0
def default_queue_suffix():
  """Get the queue suffix for the current platform."""
  queue_override = environment.get_value('QUEUE_OVERRIDE')
  if queue_override:
    return queue_suffix_for_platform(queue_override)

  return queue_suffix_for_platform(environment.platform())
Example #8
0
def save_crash_info_if_needed(testcase_id, crash_revision, job_type, crash_type,
                              crash_address, crash_frames):
  """Saves crash report for chromium project, skip otherwise."""
  if data_handler.get_project_name(job_type) != 'chromium':
    return None

  serialized_crash_stack_frames = get_symbolized_stack_bytes(
      crash_type, crash_address, crash_frames)
  if not serialized_crash_stack_frames:
    return None

  crash_info = CrashReportInfo(
      serialized_crash_stack_frames=serialized_crash_stack_frames)

  # Get product and version (required).
  platform = environment.platform()
  crash_info.product = PRODUCT_MAP[platform]
  crash_info.version = revisions.get_real_revision(
      crash_revision, job_type, display=True)

  # Update crash_info object with bot information and testcase id.
  crash_info.bot_id = environment.get_value('BOT_NAME')
  crash_info.testcase_id = int(testcase_id)

  # Store CrashInfo metadata.
  crash_report_metadata = crash_info.to_report_metadata()
  crash_report_metadata.job_type = job_type
  crash_report_metadata.crash_revision = crash_revision
  crash_report_metadata.put()

  logs.log('Created crash report entry for testcase %s.' % testcase_id)
  return crash_info
Example #9
0
def _reproduce_crash(testcase_url, build_directory):
    """Reproduce a crash."""
    _prepare_initial_environment(build_directory)

    # Validate the test case URL and fetch the tool's configuration.
    testcase_id = _get_testcase_id_from_url(testcase_url)
    configuration = config.ReproduceToolConfiguration(testcase_url)

    testcase = _get_testcase(testcase_id, configuration)
    testcase_path = _download_testcase(testcase_id, testcase, configuration)
    _update_environment_for_testcase(testcase, build_directory)

    # Validate that we're running on the right platform for this test case.
    platform = environment.platform().lower()
    if testcase.platform == 'android' and platform == 'linux':
        _prepare_environment_for_android()
    elif testcase.platform == 'android' and platform != 'linux':
        raise errors.ReproduceToolUnrecoverableError(
            'The ClusterFuzz environment only supports running Android test cases '
            'on Linux host machines. Unable to reproduce the test case on '
            '{current_platform}.'.format(current_platform=platform))
    elif testcase.platform != platform:
        raise errors.ReproduceToolUnrecoverableError(
            'The specified test case was discovered on {testcase_platform}. '
            'Unable to attempt to reproduce it on {current_platform}.'.format(
                testcase_platform=testcase.platform,
                current_platform=platform))

    timeout = environment.get_value('TEST_TIMEOUT')
    result = testcase_manager.test_for_crash_with_retries(
        testcase, testcase_path, timeout)

    return result
Example #10
0
  def _get_fuzzer_binary_name_and_path(self):
    """Returns the fuzzer binary name and its path."""
    # Fuchsia doesn't use file paths to call fuzzers, just the name of the
    # fuzzer, so we set both from FUZZ_TARGET here.
    if environment.platform() == 'FUCHSIA':
      fuzzer_binary_name = fuzzer_path = environment.get_value('FUZZ_TARGET')
      return fuzzer_binary_name, fuzzer_path
    build_directory = environment.get_value('BUILD_DIR')

    if not build_directory:
      raise BuiltinFuzzerException('BUILD_DIR environment variable is not set.')

    fuzzers = fuzzers_utils.get_fuzz_targets(build_directory)

    if not fuzzers:
      raise BuiltinFuzzerException(
          'No fuzzer binaries found in |BUILD_DIR| directory.')

    fuzzer_binary_name = environment.get_value('FUZZ_TARGET')
    if fuzzer_binary_name:
      fuzzer_path = _get_fuzzer_path(fuzzers, fuzzer_binary_name)
    else:
      fuzzer_path = random.SystemRandom().choice(fuzzers)
      fuzzer_binary_name = os.path.basename(fuzzer_path)
    return fuzzer_binary_name, fuzzer_path
Example #11
0
def find_fuzzer_path(build_directory, fuzzer_name):
  """Find the fuzzer path with the given name."""
  if environment.platform() == 'FUCHSIA':
    # Fuchsia targets are not on disk.
    return fuzzer_name

  # TODO(ochang): This is necessary for legacy testcases, which include the
  # project prefix in arguments. Remove this in the near future.
  project_name = environment.get_value('PROJECT_NAME')
  legacy_name_prefix = ''
  if project_name:
    legacy_name_prefix = project_name + '_'

  fuzzer_filename = environment.get_executable_filename(fuzzer_name)
  for root, _, files in os.walk(build_directory):
    for filename in files:
      if (legacy_name_prefix + filename == fuzzer_name or
          filename == fuzzer_filename):
        return os.path.join(root, filename)

  # This is an expected case when doing regression testing with old builds
  # that do not have that fuzz target. It can also happen when a host sends a
  # message to an untrusted worker that just restarted and lost information on
  # build directory.
  logs.log_warn('Fuzzer: %s not found in build_directory: %s.' %
                (fuzzer_name, build_directory))
  return None
    def setUp(self):
        if environment.platform() != 'LINUX':
            self.skipTest(
                'Minijail tests are only applicable for linux platform.')

        super(CorpusPruningTestMinijail, self).setUp()
        os.environ['USE_MINIJAIL'] = 'True'
Example #13
0
def _setup_x():
    """Start Xvfb and blackbox before running the test application."""
    if environment.platform() != 'LINUX':
        return []

    if environment.is_engine_fuzzer_job():
        # For engine fuzzer jobs like AFL, libFuzzer, Xvfb is not needed as the
        # those fuzz targets do not needed a UI.
        return []

    environment.set_value('DISPLAY', DISPLAY)

    print('Starting Xvfb...')
    xvfb_runner = new_process.ProcessRunner('/usr/bin/Xvfb')
    xvfb_process = xvfb_runner.run(additional_args=[
        DISPLAY, '-screen', '0', '1280x1024x24', '-ac', '-nolisten', 'tcp'
    ])
    time.sleep(PROCESS_START_WAIT_SECONDS)

    print('Starting blackbox...')
    blackbox_runner = new_process.ProcessRunner('/usr/bin/blackbox')
    blackbox_process = blackbox_runner.run()
    time.sleep(PROCESS_START_WAIT_SECONDS)

    # Return all handles we create so they can be terminated properly at exit.
    return [xvfb_process, blackbox_process]
Example #14
0
def is_memory_tool_crash(stacktrace):
    """Return true if it is a memory debugging tool crash."""
    # Job-specific generic checks.
    crash_signature = environment.get_value('CRASH_SIGNATURE')
    if crash_signature and re.search(crash_signature, stacktrace):
        return True

    # Android specific check.
    # FIXME: Share this regex with stack_analyzer.
    if (environment.platform() == 'ANDROID' and re.match(
            r'.*signal.*\(SIG.*fault addr ([^ ]*)', stacktrace, re.DOTALL)):
        return True

    # Check if we have a complete stacktrace by location stacktrace end marker.
    # If not, bail out.
    if not has_marker(stacktrace, STACKTRACE_END_MARKERS):
        return False

    # Check if have a UBSan error.
    if has_ubsan_error(stacktrace):
        return True

    # Check if have a stacktrace start marker.
    if has_marker(stacktrace, STACKTRACE_TOOL_MARKERS):
        return True

    return False
Example #15
0
def use_mutator_plugin(target_name, extra_env, chroot):
    """Decide whether to use a mutator plugin. If yes and there is a usable plugin
  available for |target_name|, then add it to LD_PRELOAD in |extra_env|, add
  chroot bindings if |chroot| is not None, and return True."""

    # TODO(metzman): Support Windows.
    if environment.platform() == 'WINDOWS':
        return False

    mutator_plugin_path = mutator_plugin.get_mutator_plugin(target_name)
    if not mutator_plugin_path:
        return False

    logs.log('Using mutator plugin: %s' % mutator_plugin_path)
    # TODO(metzman): Change the strategy to record which plugin was used, and
    # not simply that a plugin was used.
    extra_env['LD_PRELOAD'] = mutator_plugin_path

    if chroot:
        mutator_plugin_dir = os.path.dirname(mutator_plugin_path)
        chroot.add_binding(
            minijail.ChrootBinding(mutator_plugin_dir, mutator_plugin_dir,
                                   False))

    return True
Example #16
0
def _get_testcase_file_and_path(testcase):
  """Figure out the relative path and input directory for this testcase."""
  testcase_absolute_path = testcase.absolute_path

  # This hack is needed so that we can run a testcase generated on windows, on
  # linux. os.path.isabs return false on paths like c:\a\b\c.
  testcase_path_is_absolute = (
      testcase_absolute_path[1:3] == ':\\' or
      os.path.isabs(testcase_absolute_path))

  # Fix os.sep in testcase path if we are running this on non-windows platform.
  # It is unusual to have '\\' on linux paths, so substitution should be safe.
  if environment.platform() != 'WINDOWS' and '\\' in testcase_absolute_path:
    testcase_absolute_path = testcase_absolute_path.replace('\\', os.sep)

  # Default directory for testcases.
  input_directory = environment.get_value('FUZZ_INPUTS')
  if not testcase_path_is_absolute:
    testcase_path = os.path.join(input_directory, testcase_absolute_path)
    return input_directory, testcase_path

  # Check if the testcase is on a nfs data bundle. If yes, then just
  # return it without doing root directory path fix.
  nfs_root = environment.get_value('NFS_ROOT')
  if nfs_root and testcase_absolute_path.startswith(nfs_root):
    return input_directory, testcase_absolute_path

  # Root directory can be different on bots. Fix the path to account for this.
  root_directory = environment.get_value('ROOT_DIR')
  search_string = '%s%s%s' % (os.sep, _BOT_DIR, os.sep)
  search_index = testcase_absolute_path.find(search_string)
  relative_path = testcase_absolute_path[search_index + len(search_string):]
  testcase_path = os.path.join(root_directory, _BOT_DIR, relative_path)

  return input_directory, testcase_path
Example #17
0
def find_fuzzer_path(build_directory, fuzzer_name, is_blackbox=False):
    """Find the fuzzer path with the given name."""
    # Blackbox fuzzers are special cases. They run from the fuzzers directory
    # rather than using a target from the build archive.
    if is_blackbox:
        fuzzer_directory = environment.get_value('FUZZERS_DIR')
        fuzzer_directory = os.path.join(fuzzer_directory, fuzzer_name)
        fuzzer = data_types.Fuzzer.query(
            data_types.Fuzzer.name == fuzzer_name).get()
        return os.path.join(fuzzer_directory, fuzzer.executable_path)

    if not build_directory:
        # Grey-box fuzzers might not have the build directory for a particular job
        # configuration when doing variant task testing (e.g. Android on-device
        # fuzz target might not exist on host). In this case, treat it similar to
        # target not found by returning None.
        logs.log_warn('No build directory found for fuzzer: %s' % fuzzer_name)
        return None

    if environment.platform() == 'FUCHSIA':
        # Fuchsia targets are not on disk.
        return fuzzer_name

    if environment.platform() == 'ANDROID_KERNEL':
        return os.path.join(build_directory, 'syzkaller', 'bin', 'syz-manager')

    # TODO(ochang): This is necessary for legacy testcases, which include the
    # project prefix in arguments. Remove this in the near future.
    project_name = environment.get_value('PROJECT_NAME')
    legacy_name_prefix = u''
    if project_name:
        legacy_name_prefix = project_name + u'_'

    fuzzer_filename = environment.get_executable_filename(fuzzer_name)
    for root, _, files in shell.walk(build_directory):
        for filename in files:
            if (legacy_name_prefix + filename == fuzzer_name
                    or filename == fuzzer_filename):
                return os.path.join(root, filename)

    # This is an expected case when doing regression testing with old builds
    # that do not have that fuzz target. It can also happen when a host sends a
    # message to an untrusted worker that just restarted and lost information on
    # build directory.
    logs.log_warn('Fuzzer: %s not found in build_directory: %s.' %
                  (fuzzer_name, build_directory))
    return None
Example #18
0
def clear_testcase_directories():
    """Clears the testcase directories."""
    remove_directory(environment.get_value("FUZZ_INPUTS"), recreate=True)
    remove_directory(environment.get_value("FUZZ_INPUTS_DISK"), recreate=True)

    if environment.platform() == "ANDROID":
        from platforms import android

        android.device.clear_testcase_directory()
    if environment.platform() == "FUCHSIA":
        from platforms import fuchsia

        fuchsia.device.clear_testcase_directory()
    if environment.is_trusted_host():
        from bot.untrusted_runner import file_host

        file_host.clear_testcase_directories()
Example #19
0
def initialize_timezone_from_environment():
  """Initializes timezone for date functions based on environment."""
  plt = environment.platform()
  if plt == 'WINDOWS':
    return

  # Only available on Unix platforms.
  time.tzset()
Example #20
0
def _wait_process(
    process,
    timeout,
    input_data=None,
    terminate_before_kill=False,
    terminate_wait_time=None,
):
    """Waits until either the process exits or times out.

    Args:
      process: A subprocess.Popen object.
      timeout: Maximum number of seconds to wait for before sending a signal.
      input_data: Input to be sent to the process.
      terminate_before_kill: A bool indicating that SIGTERM should be sent to
          the process first before SIGKILL (to let the SIGTERM handler run).
      terminate_wait_time: Maximum number of seconds to wait for the SIGTERM
          handler.

    Returns:
      A ProcessResult.
    """
    result = ProcessResult()
    is_windows = environment.platform() == "WINDOWS"

    # On Windows, terminate() just calls Win32 API function TerminateProcess()
    # which is equivalent to process kill. So, skip terminate_before_kill.
    if terminate_before_kill and not is_windows:
        first_timeout_function = process.terminate

        # Use a second timer to send the process kill.
        second_timer = threading.Timer(timeout + terminate_wait_time,
                                       _end_process, [process.kill, result])
    else:
        first_timeout_function = process.kill
        second_timer = None

    first_timer = threading.Timer(timeout, _end_process,
                                  [first_timeout_function, result])

    output = None
    start_time = time.time()

    try:
        first_timer.start()
        if second_timer:
            second_timer.start()

        output = process.communicate(input_data)[0]
    finally:
        first_timer.cancel()

        if second_timer:
            second_timer.cancel()

    result.return_code = process.poll()
    result.output = output
    result.time_executed = time.time() - start_time
    return result
Example #21
0
def do_mutator_plugin():
  """Return whether or not to use a mutator_plugin."""
  # TODO(metzman): Support Windows.
  if environment.platform() == 'WINDOWS':
    return False

  return engine_common.decide_with_probability(
      engine_common.get_strategy_probability(
          strategy.MUTATOR_PLUGIN_STRATEGY, default=MUTATOR_PLUGIN_PROBABILITY))
def select_generator(strategy_pool, fuzzer_path):
  """Pick a generator to generate new testcases before fuzzing or return
  Generator.NONE if no generator selected."""
  if environment.platform() == 'FUCHSIA':
    # Unsupported.
    return Generator.NONE

  # We can't use radamsa binary on Windows. Disable ML for now until we know it
  # works on Win.
  # These generators don't produce testcases that LPM fuzzers can use.
  if (environment.platform() == 'WINDOWS' or is_lpm_fuzz_target(fuzzer_path)):
    return Generator.NONE
  elif strategy_pool.do_strategy(strategy.CORPUS_MUTATION_ML_RNN_STRATEGY):
    return Generator.ML_RNN
  elif strategy_pool.do_strategy(strategy.CORPUS_MUTATION_RADAMSA_STRATEGY):
    return Generator.RADAMSA

  return Generator.NONE
Example #23
0
def filter_binary_path(binary_path):
    """Filters binary path to provide a local copy."""
    platform = environment.platform()

    if platform == 'ANDROID':
        # Skip symbolization when running it on bad entries like [stack:XYZ].
        if not binary_path.startswith('/') or '(deleted)' in binary_path:
            return ''

        # Initialize some helper variables.
        binary_filename = os.path.basename(binary_path)
        build_directory = environment.get_value('BUILD_DIR')
        symbols_directory = environment.get_value('SYMBOLS_DIR')

        # Try to find the library in the build directory first.
        local_binary_path = utils.find_binary_path(build_directory,
                                                   binary_path)
        if local_binary_path:
            return local_binary_path

        # We didn't find the library locally in the build directory.
        # Try finding the library in the local system library cache.
        download_system_symbols_if_needed(symbols_directory)
        local_binary_path = utils.find_binary_path(symbols_directory,
                                                   binary_path)
        if local_binary_path:
            return local_binary_path

        # Try pulling in the binary directly from the device into the
        # system library cache directory.
        local_binary_path = os.path.join(symbols_directory, binary_filename)
        adb.run_command('pull %s %s' % (binary_path, local_binary_path))
        if os.path.exists(local_binary_path):
            return local_binary_path

        # Unable to find library.
        logs.log_error('Unable to find library %s for symbolization.' %
                       binary_path)
        return ''

    if platform == 'CHROMEOS':
        # FIXME: Add code to pull binaries from ChromeOS device.
        return binary_path

    if environment.is_chromeos_system_job():
        # This conditional is True for ChromeOS system fuzzers that are running on
        # Linux. Ensure that the binary is always looked for in the chroot and not
        # in system directories.
        build_dir = environment.get_value('BUILD_DIR')
        if not binary_path.startswith(build_dir):
            # Fixup path so |binary_path| points to a binary in the chroot (probably
            # a system library).
            return os.path.join(build_dir, binary_path[1:])

    # For Linux and Mac, the binary exists locally. No work to do,
    # just return the same binary path.
    return binary_path
Example #24
0
def do_fork():
  """Return whether or not to do fork mode."""
  # TODO(metzman): Find a workaround for Windows command line limit before
  # re-enabling this.
  if environment.platform() == 'WINDOWS':
    return False

  return engine_common.decide_with_probability(
      engine_common.get_strategy_probability(
          strategy.FORK_STRATEGY, default=FORK_PROBABILITY))
Example #25
0
def _handle_unrecoverable_error_on_windows():
  """Handle non-recoverable error on Windows. This is usually either due to disk
  corruption or processes failing to terminate using regular methods. Force a
  restart for recovery."""
  if environment.platform() != 'WINDOWS':
    return

  logs.log_error('Unrecoverable error, restarting machine...')
  time.sleep(60)
  utils.restart_machine()
Example #26
0
def get_runner(fuzzer_path, temp_dir=None):
    """Get a libfuzzer runner."""
    use_minijail = environment.get_value('USE_MINIJAIL')
    build_dir = environment.get_value('BUILD_DIR')
    dataflow_build_dir = environment.get_value('DATAFLOW_BUILD_DIR')
    if use_minijail:
        # Set up chroot and runner.
        if environment.is_chromeos_system_job():
            minijail_chroot = minijail.ChromeOSChroot(build_dir)
        else:
            minijail_chroot = minijail.MinijailChroot(base_dir=temp_dir)

        # While it's possible for dynamic binaries to run without this, they need
        # to be accessible for symbolization etc. For simplicity we bind BUILD_DIR
        # to the same location within the chroot, which leaks the directory
        # structure of CF but this shouldn't be a big deal.
        minijail_chroot.add_binding(
            minijail.ChrootBinding(build_dir, build_dir, False))

        if dataflow_build_dir:
            minijail_chroot.add_binding(
                minijail.ChrootBinding(dataflow_build_dir, dataflow_build_dir,
                                       False))

        # Also bind the build dir to /out to make it easier to hardcode references
        # to data files.
        minijail_chroot.add_binding(
            minijail.ChrootBinding(build_dir, '/out', False))

        minijail_bin = os.path.join(minijail_chroot.directory, 'bin')
        shell.create_directory(minijail_bin)

        # Set up /bin with llvm-symbolizer to allow symbolized stacktraces.
        # Don't copy if it already exists (e.g. ChromeOS chroot jail).
        llvm_symbolizer_source_path = environment.get_llvm_symbolizer_path()
        llvm_symbolizer_destination_path = os.path.join(
            minijail_bin, 'llvm-symbolizer')
        if not os.path.exists(llvm_symbolizer_destination_path):
            shutil.copy(llvm_symbolizer_source_path,
                        llvm_symbolizer_destination_path)

        # copy /bin/sh, necessary for system().
        if not environment.is_chromeos_system_job():
            # The chroot has its own shell we don't need to copy (and probably
            # shouldn't because of library differences).
            shutil.copy(os.path.realpath('/bin/sh'),
                        os.path.join(minijail_bin, 'sh'))

        runner = MinijailLibFuzzerRunner(fuzzer_path, minijail_chroot)
    elif environment.platform() == 'FUCHSIA':
        runner = FuchsiaQemuLibFuzzerRunner(fuzzer_path)
    else:
        runner = LibFuzzerRunner(fuzzer_path)

    return runner
Example #27
0
  def run(self,
          file_path=None,
          gestures=None,
          arguments=None,
          timeout=None,
          log_command=False,
          use_fresh_profile=False):
    """Run the test."""
    if file_path is None:
      file_path = self.file_path

    if gestures is None:
      gestures = self.gestures

    if arguments is None:
      arguments = self.arguments

    # TODO(mbarbella): Dynamic timeout adjustment.
    if timeout is None:
      timeout = self.timeout

    needs_http = self.testcase.http_flag
    profile_index = self._get_profile_index()

    if use_fresh_profile and environment.get_value('USER_PROFILE_ARG'):
      shell.remove_directory(
          testcase_manager.get_user_profile_directory(profile_index))

    # For Android, we need to sync our local testcases directory with the one on
    # the device.
    if environment.platform() == 'ANDROID':
      android.device.push_testcases_to_device()
    elif environment.is_trusted_host():
      from bot.untrusted_runner import file_host
      file_host.push_testcases_to_worker()

    # If we need to write a command line file, only do so if the arguments have
    # changed.
    arguments_changed = arguments != self._previous_arguments
    self._previous_arguments = arguments

    command = testcase_manager.get_command_line_for_application(
        file_to_run=file_path,
        app_args=arguments,
        needs_http=needs_http,
        user_profile_index=profile_index,
        write_command_line_file=arguments_changed)
    if log_command:
      logs.log('Executing command: %s' % command)

    return_code, crash_time, output = process_handler.run_process(
        command, timeout=timeout, gestures=gestures)

    self._release_profile(profile_index)
    return CrashResult(return_code, crash_time, output)
Example #28
0
def android_device_required(func):
    """Skip Android-specific tests if we cannot run them."""
    reason = None
    if not environment.get_value('ANDROID_SERIAL'):
        reason = 'Android device tests require that ANDROID_SERIAL is set.'
    elif not environment.get_value('INTEGRATION'):
        reason = 'Integration tests are not enabled.'
    elif environment.platform() != 'LINUX':
        reason = 'Android device tests can only run on a Linux host.'

    return unittest.skipIf(reason is not None, reason)(func)
Example #29
0
def get_radamsa_path():
    """Return path to radamsa binary for current platform."""
    bin_directory_path = os.path.join(
        os.path.dirname(os.path.realpath(__file__)), 'bin')
    platform = environment.platform()
    if platform == 'LINUX':
        return os.path.join(bin_directory_path, 'linux', 'radamsa')

    if platform == 'MAC':
        return os.path.join(bin_directory_path, 'mac', 'radamsa')

    return None
Example #30
0
  def setUp(self):
    if environment.platform() != 'LINUX':
      self.skipTest('Minijail tests are only applicable for linux platform.')

    test_helpers.patch(self, [
        'system.minijail._get_minijail_path',
        'system.minijail.MinijailChroot._mknod',
    ])

    test_helpers.patch_environ(self)

    self.mock._get_minijail_path.return_value = '/sbin/minijail'  # pylint: disable=protected-access