• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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