# 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 os # From clusterfuzz: src/python/crash_analysis/crash_analyzer.py # Used to get the beginning of the stacktrace. STACKTRACE_TOOL_MARKERS = [ b'AddressSanitizer', b'ASAN:', b'CFI: Most likely a control flow integrity violation;', b'ERROR: libFuzzer', b'KASAN:', b'LeakSanitizer', b'MemorySanitizer', b'ThreadSanitizer', b'UndefinedBehaviorSanitizer', b'UndefinedSanitizer', ] # From clusterfuzz: src/python/crash_analysis/crash_analyzer.py # Used to get the end of the stacktrace. STACKTRACE_END_MARKERS = [ b'ABORTING', b'END MEMORY TOOL REPORT', b'End of process memory map.', b'END_KASAN_OUTPUT', b'SUMMARY:', b'Shadow byte and word', b'[end of stack trace]', b'\nExiting', b'minidump has been written', ] def parse_fuzzer_output(fuzzer_output, out_dir): """Parses the fuzzer output from a fuzz target binary. Args: fuzzer_output: A fuzz target binary output string to be parsed. out_dir: The location to store the parsed output files. """ # Get index of key file points. for marker in STACKTRACE_TOOL_MARKERS: marker_index = fuzzer_output.find(marker) if marker_index: begin_stack = marker_index break end_stack = -1 for marker in STACKTRACE_END_MARKERS: marker_index = fuzzer_output.find(marker) if marker_index: end_stack = marker_index + len(marker) break if begin_stack is None or end_stack is None: return summary_str = fuzzer_output[begin_stack:end_stack] if not summary_str: return # Write sections of fuzzer output to specific files. summary_file_path = os.path.join(out_dir, 'bug_summary.txt') with open(summary_file_path, 'ab') as summary_handle: summary_handle.write(summary_str)