1# Copyright 2021 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Module for parsing stacks from fuzz targets.""" 15 16import logging 17 18# From clusterfuzz: src/python/crash_analysis/crash_analyzer.py 19# Used to get the beginning of the stacktrace. 20STACKTRACE_TOOL_MARKERS = [ 21 b'AddressSanitizer', 22 b'ASAN:', 23 b'CFI: Most likely a control flow integrity violation;', 24 b'ERROR: libFuzzer', 25 b'KASAN:', 26 b'LeakSanitizer', 27 b'MemorySanitizer', 28 b'ThreadSanitizer', 29 b'UndefinedBehaviorSanitizer', 30 b'UndefinedSanitizer', 31] 32 33# From clusterfuzz: src/python/crash_analysis/crash_analyzer.py 34# Used to get the end of the stacktrace. 35STACKTRACE_END_MARKERS = [ 36 b'ABORTING', 37 b'END MEMORY TOOL REPORT', 38 b'End of process memory map.', 39 b'END_KASAN_OUTPUT', 40 b'SUMMARY:', 41 b'Shadow byte and word', 42 b'[end of stack trace]', 43 b'\nExiting', 44 b'minidump has been written', 45] 46 47 48def parse_fuzzer_output(fuzzer_output, parsed_output_file_path): 49 """Parses the fuzzer output from a fuzz target binary. 50 51 Args: 52 fuzzer_output: A fuzz target binary output string to be parsed. 53 parsed_output_file_path: The location to store the parsed output. 54 """ 55 # Get index of key file points. 56 begin_stack = None 57 for marker in STACKTRACE_TOOL_MARKERS: 58 marker_index = fuzzer_output.find(marker) 59 if marker_index != -1: 60 begin_stack = marker_index 61 break 62 63 if begin_stack is None: 64 logging.error( 65 b'Could not find a begin stack marker (%s) in fuzzer output:\n%s', 66 STACKTRACE_TOOL_MARKERS, fuzzer_output) 67 return 68 69 end_stack = None 70 for marker in STACKTRACE_END_MARKERS: 71 marker_index = fuzzer_output.find(marker) 72 if marker_index != -1: 73 end_stack = marker_index + len(marker) 74 break 75 76 if end_stack is None: 77 logging.error( 78 b'Could not find an end stack marker (%s) in fuzzer output:\n%s', 79 STACKTRACE_END_MARKERS, fuzzer_output) 80 return 81 82 summary_str = fuzzer_output[begin_stack:end_stack] 83 84 # Write sections of fuzzer output to specific files. 85 with open(parsed_output_file_path, 'ab') as summary_handle: 86 summary_handle.write(summary_str) 87