def reproduce_crash(self): """Reproduce the crash, running gestures if necessary.""" with Xvfb(self.options.disable_xvfb) as display_name: self.environment['DISPLAY'] = display_name # stdin needs to be UserStdin. Otherwise, it wouldn't work with gdb. process = common.start_execute(self.binary_path, self.args, self.build_directory, env=self.environment, stdin=common.UserStdin(), redirect_stderr_to_stdout=True) if self.gestures: self.run_gestures(process, display_name) # read_buffer_length needs to be 1. Otherwise, it wouldn't work well with # gdb. err, out = common.wait_execute( process, exit_on_error=False, timeout=self.timeout, stdout_transformer=output_transformer.Identity(), read_buffer_length=1) return err, symbolize(out, self.source_directory)
def reproduce_crash(self): """Reproduce crash on Android.""" android.reset(self.testcase.android_package_name) android.reboot() android.ensure_active() android.clear_log() ret_value, _ = android.adb_shell( 'am start -a android.intent.action.MAIN ' "-n {package_name}/{class_name} '{testcase_url}'".format( package_name=self.testcase.android_package_name, class_name=self.testcase.android_main_class_name, testcase_url=self.get_testcase_url()), redirect_stderr_to_stdout=True, stdout_transformer=output_transformer.Identity()) time.sleep(TEST_TIMEOUT) run_monkey_gestures_if_needed(self.testcase.android_package_name, self.testcase.gestures) output = android.get_log() android.kill(self.testcase.android_package_name) lib_tmp_dir_path = tempfile.mkdtemp(dir=common.CLUSTERFUZZ_TMP_DIR) symbolized_output = symbolize( output=android.fix_lib_path( content=android.filter_log(output), search_paths=[ self.binary_provider.get_unstripped_lib_dir_path(), self.binary_provider.get_android_libclang_dir_path() ], lib_tmp_dir_path=lib_tmp_dir_path), source_dir_path=self.binary_provider.get_source_dir_path()) common.delete_if_exists(lib_tmp_dir_path) return ret_value, symbolized_output
def symbolize(output, source_dir_path): """Symbolize a stacktrace.""" output = output.strip() if not output: # If no input, nothing to symbolize. Bail out, otherwise # we hang inside symbolizer. return '' asan_symbolizer_location = os.path.join( source_dir_path, os.path.join('tools', 'valgrind', 'asan', 'asan_symbolize.py')) symbolizer_proxy_location = common.get_resource(0755, 'asan_symbolize_proxy.py') _, symbolized_out = common.execute( asan_symbolizer_location, '', os.path.expanduser('~'), env={ 'LLVM_SYMBOLIZER_PATH': symbolizer_proxy_location, 'CHROMIUM_SRC': source_dir_path }, capture_output=True, exit_on_error=True, stdout_transformer=output_transformer.Identity(), stdin=common.StringStdin(output + '\0'), redirect_stderr_to_stdout=True) logger.info(symbolized_out) return symbolized_out
def post_run_symbolize(self, output): """Symbolizes non-libfuzzer chrome jobs.""" if not output.strip(): # If no input, nothing to symbolize. Bail out, otherwise # we hang inside symbolizer. return '' asan_symbolizer_location = os.path.join( self.source_directory, os.path.join('tools', 'valgrind', 'asan', 'asan_symbolize.py')) symbolizer_proxy_location = common.get_resource( 0755, 'asan_symbolize_proxy.py') _, symbolized_out = common.execute( asan_symbolizer_location, '', os.path.expanduser('~'), env={ 'LLVM_SYMBOLIZER_PATH': symbolizer_proxy_location, 'CHROMIUM_SRC': self.source_directory }, capture_output=True, exit_on_error=True, stdout_transformer=output_transformer.Identity(), input_str=output + '\0', redirect_stderr_to_stdout=True) logger.info(symbolized_out) return symbolized_out
def wait_execute(proc, exit_on_error, capture_output=True, print_output=True, timeout=None, stdout_transformer=None, stderr_transformer=None, read_buffer_length=DEFAULT_READ_BUFFER_LENGTH): """Looks after a command as it runs, and prints/returns its output after.""" if stdout_transformer is None: stdout_transformer = output_transformer.Hidden() if stderr_transformer is None: stderr_transformer = output_transformer.Identity() logger.debug('---------------------------------------') wait_timeout(proc, timeout) output_chunks = [] stdout_transformer.set_output(sys.stdout) stderr_transformer.set_output(sys.stderr) # Stdout is printed as the process runs because some commands (e.g. ninja) # might take a long time to run. for chunk in iter(lambda: proc.stdout.read(read_buffer_length), b''): if print_output: local_logging.send_output(chunk) stdout_transformer.process(chunk) if capture_output: # According to: http://stackoverflow.com/questions/19926089, this is the # fastest way to build strings. output_chunks.append(chunk) # We cannot read from stderr because it might cause a hang. # Therefore, we use communicate() to get stderr instead. # See: https://github.com/google/clusterfuzz-tools/issues/278 stdout_data, stderr_data = proc.communicate() stdout_data = stdout_data or '' stderr_data = stderr_data or '' kill(proc) for (transformer, data) in [(stdout_transformer, stdout_data), (stderr_transformer, stderr_data)]: if capture_output: output_chunks.append(data) if print_output: local_logging.send_output(data) transformer.process(data) transformer.flush() logger.debug('---------------------------------------') if proc.returncode != 0: logger.debug('| Return code is non-zero (%d).', proc.returncode) if exit_on_error: logger.debug('| Exit.') raise error.CommandFailedError(proc.args, proc.returncode, stderr_data) return proc.returncode, ''.join(output_chunks)
def install_build_deps_32bit(source_dir): """Run install-build-deps.sh.""" # preexec_fn is required to be None. Otherwise, it'd fail with: # 'sudo: no tty present and no askpass program specified'. common.execute( 'build/install-build-deps.sh', '--lib32 --syms --no-prompt', source_dir, stdout_transformer=output_transformer.Identity(), preexec_fn=None, redirect_stderr_to_stdout=True)
def reproduce_crash(self): """Reproduce the crash.""" return common.execute(self.binary_path, self.args, os.path.dirname(self.binary_path), env=self.environment, exit_on_error=False, timeout=TEST_TIMEOUT, stdout_transformer=output_transformer.Identity(), redirect_stderr_to_stdout=True)
def test_print(self): """Test printing dot every n characters.""" self.output = StringIO.StringIO() transformer = output_transformer.Identity() transformer.set_output(self.output) transformer.process('a' * 1001) transformer.flush() self.assertEqual('a' * 1001, self.output.getvalue()) self.output.close()
def install_deps(self): """Install deps.""" super(ClankiumBuilder, self).install_deps() # preexec_fn is required to be None. Otherwise, it'd fail with: # 'sudo: no tty present and no askpass program specified'. # See why PATH is added: # https://github.com/google/clusterfuzz-tools/issues/497 common.execute( 'sudo', 'PATH=$PATH build/install-build-deps-android.sh', self.get_source_dir_path(), stdout_transformer=output_transformer.Identity(), preexec_fn=None, redirect_stderr_to_stdout=True)
def reproduce_crash(self): """Reproduce the crash.""" # read_buffer_length needs to be 1, and stdin needs to be UserStdin. # Otherwise, it wouldn't work well with gdb. return common.execute(self.binary_path, self.args, self.build_directory, env=self.environment, exit_on_error=False, timeout=self.timeout, stdout_transformer=output_transformer.Identity(), redirect_stderr_to_stdout=True, stdin=common.UserStdin(), read_buffer_length=1)
def install_build_deps(source_dir, include_lib32): """Run install-build-deps.sh.""" flags = '--syms --no-prompt' if include_lib32: flags += ' --lib32' # preexec_fn is required to be None. Otherwise, it'd fail with: # 'sudo: no tty present and no askpass program specified'. # See why PATH is added: # https://github.com/google/clusterfuzz-tools/issues/497 common.execute( 'sudo', 'PATH=$PATH build/install-build-deps.sh %s' % flags, source_dir, stdout_transformer=output_transformer.Identity(), preexec_fn=None, redirect_stderr_to_stdout=True)
def reproduce_crash(self): """Reproduce the crash, running gestures if necessary.""" with Xvfb(self.options.disable_xvfb) as display_name: self.environment['DISPLAY'] = display_name process = common.start_execute(self.binary_path, self.args, os.path.dirname(self.binary_path), env=self.environment, redirect_stderr_to_stdout=True) if self.gestures: self.run_gestures(process, display_name) err, out = common.wait_execute( process, exit_on_error=False, timeout=TEST_TIMEOUT, stdout_transformer=output_transformer.Identity()) return err, self.post_run_symbolize(out)
def get_log(): """Get logs.""" _, output = adb('logcat -d -v brief *:I', redirect_stderr_to_stdout=True, stdout_transformer=output_transformer.Identity()) return output