blob: 69c44bc2ece0221e9536a03962a473ff955d914c [file] [log] [blame]
# 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 = [
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, 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, 'ab') as summary_handle:
summary_handle.write(summary_str)