# Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for parsing stacks from fuzz targets.""" import logging # From clusterfuzz: src/python/crash_analysis/crash_analyzer.py # Used to get the beginning of the stacktrace. STACKTRACE_TOOL_MARKERS = [ 'AddressSanitizer', 'ASAN:', 'CFI: Most likely a control flow integrity violation;', 'ERROR: libFuzzer', 'KASAN:', 'LeakSanitizer', 'MemorySanitizer', 'ThreadSanitizer', 'UndefinedBehaviorSanitizer', 'UndefinedSanitizer', ] # From clusterfuzz: src/python/crash_analysis/crash_analyzer.py # Used to get the end of the stacktrace. STACKTRACE_END_MARKERS = [ 'ABORTING', 'END MEMORY TOOL REPORT', 'End of process memory map.', 'END_KASAN_OUTPUT', 'SUMMARY:', 'Shadow byte and word', '[end of stack trace]', '\nExiting', 'minidump has been written', ] def parse_fuzzer_output(fuzzer_output, parsed_output_file_path): """Parses the fuzzer output from a fuzz target binary. Args: fuzzer_output: A fuzz target binary output string to be parsed. parsed_output_file_path: The location to store the parsed output. """ # Get index of key file points. begin_stack = None for marker in STACKTRACE_TOOL_MARKERS: marker_index = fuzzer_output.find(marker) if marker_index != -1: begin_stack = marker_index break if begin_stack is None: logging.error( b'Could not find a begin stack marker (%s) in fuzzer output:\n%s', STACKTRACE_TOOL_MARKERS, fuzzer_output) return end_stack = None for marker in STACKTRACE_END_MARKERS: marker_index = fuzzer_output.find(marker) if marker_index != -1: end_stack = marker_index + len(marker) break if end_stack is None: logging.error( b'Could not find an end stack marker (%s) in fuzzer output:\n%s', STACKTRACE_END_MARKERS, fuzzer_output) return summary_str = fuzzer_output[begin_stack:end_stack] # Write sections of fuzzer output to specific files. with open(parsed_output_file_path, 'a') as summary_handle: summary_handle.write(summary_str)