def test_windows(self): """Tests that it behaves as intended on Windows.""" self.mock.platform.return_value = 'WINDOWS' executable_with_extension = self.EXECUTABLE + '.exe' # Test that it adds an extension if needed. self.assertEqual(executable_with_extension, environment.get_executable_filename(self.EXECUTABLE)) # Now test that it doesn't add an extension when not needed. self.assertEqual( executable_with_extension, environment.get_executable_filename(executable_with_extension))
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 = 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.encode() + 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 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 _get_fuzzer_path(target_list, fuzzer_name): """Return the full fuzzer path and actual binary name of |fuzzer_name|.""" fuzzer_filename = environment.get_executable_filename(fuzzer_name) for path in target_list: if os.path.basename(path) == fuzzer_filename: return path raise BuiltinFuzzerException('Failed to find chosen target ' + fuzzer_name)
def set_environment_vars(search_directories, app_path='APP_PATH'): """Set build-related environment variables (APP_PATH, APP_DIR etc) by walking through the build directory.""" app_name = environment.get_value('APP_NAME') llvm_symbolizer_filename = environment.get_executable_filename( 'llvm-symbolizer') llvm_symbolizer_path = None gn_args_filename = 'args.gn' gn_args_path = None platform = environment.platform() absolute_file_path = None app_directory = None # Chromium specific folder to ignore. initialexe_folder_path = '%sinitialexe' % os.path.sep for search_directory in search_directories: for root, _, files in os.walk(search_directory): # .dSYM folder contain symbol files on Mac and should # not be searched for application binary. if platform == 'MAC' and '.dSYM' in root: continue # Ignore some folders on Windows. if (platform == 'WINDOWS' and (initialexe_folder_path in root)): continue for filename in files: if not absolute_file_path and filename == app_name: absolute_file_path = os.path.join(root, filename) app_directory = os.path.dirname(absolute_file_path) # We don't want to change the state of system binaries. if not environment.get_value('SYSTEM_BINARY_DIR'): os.chmod(absolute_file_path, 0750) environment.set_value(app_path, absolute_file_path) environment.set_value('APP_DIR', app_directory) if not gn_args_path and filename == gn_args_filename: gn_args_path = os.path.join(root, gn_args_filename) environment.set_value('GN_ARGS_PATH', gn_args_path) if (not llvm_symbolizer_path and filename == llvm_symbolizer_filename and not environment.get_value('USE_DEFAULT_LLVM_SYMBOLIZER')): llvm_symbolizer_path = os.path.join(root, llvm_symbolizer_filename) environment.set_value('LLVM_SYMBOLIZER_PATH', llvm_symbolizer_path)
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
def find_fuzzer_path(build_directory, fuzzer_name): """Find the fuzzer path with the given 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) logs.log_warn('Fuzzer: %s not found in build_directory: %s.' % (fuzzer_name, build_directory)) return None
def terminate_stale_application_instances(): """Kill stale instances of the application running for this command.""" if environment.is_trusted_host(): from bot.untrusted_runner import remote_process_host remote_process_host.terminate_stale_application_instances() return # Stale instance cleanup is sometimes disabled for local testing. if not environment.get_value('KILL_STALE_INSTANCES', True): return additional_process_to_kill = environment.get_value( 'ADDITIONAL_PROCESSES_TO_KILL') builds_directory = environment.get_value('BUILDS_DIR') llvm_symbolizer_filename = environment.get_executable_filename( 'llvm-symbolizer') platform = environment.platform() start_time = time.time() processes_to_kill = [] # Avoid killing the test binary when running the reproduce tool. It is # commonly in-use on the side on developer workstations. if not environment.get_value('REPRODUCE_TOOL'): app_name = environment.get_value('APP_NAME') processes_to_kill += [app_name] if additional_process_to_kill: processes_to_kill += additional_process_to_kill.split(' ') processes_to_kill = [x for x in processes_to_kill if x] if platform == 'ANDROID': # Cleanup any stale adb connections. device_serial = environment.get_value('ANDROID_SERIAL') adb_search_string = 'adb -s %s' % device_serial # Terminate llvm symbolizer processes matching exact path. This is important # for Android where multiple device instances run on same host. llvm_symbolizer_path = environment.get_llvm_symbolizer_path() terminate_processes_matching_cmd_line( [adb_search_string, llvm_symbolizer_path], kill=True) # Make sure device is online and rooted. android.adb.run_as_root() # Make sure to reset SE Linux Permissive Mode (might be lost in reboot). android.settings.change_se_linux_to_permissive_mode() # Make sure that device forwarder is running (might be lost in reboot or # process crash). android.device.setup_host_and_device_forwarder_if_needed() # Make sure that package optimization is complete (might be triggered due to # unexpected circumstances). android.app.wait_until_optimization_complete() # Reset application state, which kills its pending instances and re-grants # the storage permissions. android.app.reset() elif platform == 'WINDOWS': processes_to_kill += [ 'cdb.exe', 'handle.exe', 'msdt.exe', 'openwith.exe', 'WerFault.exe', llvm_symbolizer_filename, ] terminate_processes_matching_names(processes_to_kill, kill=True) terminate_processes_matching_cmd_line(builds_directory, kill=True) # Artifical sleep to let the processes get terminated. time.sleep(1) else: # Handle Linux and Mac platforms. processes_to_kill += [ 'addr2line', 'atos', 'chrome-devel-sandbox', 'gdb', 'nacl_helper', 'xdotool', llvm_symbolizer_filename, ] terminate_processes_matching_names(processes_to_kill, kill=True) terminate_processes_matching_cmd_line(builds_directory, kill=True) duration = int(time.time() - start_time) if duration >= 5: logs.log('Process kill took longer than usual - %s.' % str(datetime.timedelta(seconds=duration)))
def test_non_windows(self, platform): """Tests that it behaves as intended on platforms that aren't Windows.""" self.mock.platform.return_value = platform self.assertEqual(self.EXECUTABLE, environment.get_executable_filename(self.EXECUTABLE))