| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import logging |
| 6 import re |
| 7 |
| 8 from crash import callstack_detectors |
| 9 from crash.callstack_filters import FilterFramesAfterBlinkGeneratedCode |
| 10 from crash.callstack_filters import FilterJavaJreSdkFrames |
| 11 from crash.callstack_filters import FilterV8FramesForV8APIBindingCode |
| 12 from crash.callstack_filters import FilterV8FramesIfV8NotInTopFrames |
| 13 from crash.callstack_filters import KeepV8FramesIfV8GeneratedJITCrash |
| 14 from crash.callstack_filters import KeepTopNFrames |
| 15 from crash.flag_manager import ParsingFlag |
| 16 from crash.flag_manager import FlagManager |
| 17 from crash.stacktrace import CallStackBuffer |
| 18 from crash.stacktrace import StackFrame |
| 19 from crash.stacktrace import StacktraceBuffer |
| 20 from crash.stacktrace_parser import StacktraceParser |
| 21 from crash.type_enums import CallStackFormatType |
| 22 from crash.type_enums import LanguageType |
| 23 from crash.type_enums import SanitizerType |
| 24 |
| 25 TOP_FRAME_HAS_NO_SYMBOLS_REGEX = re.compile( |
| 26 r'.*#0 0x[0-9a-f]+ \(<unknown module>\).*') |
| 27 SUMMARY_MARKER = 'SUMMARY:' |
| 28 JAVA_FATAL_EXCEPTION_REGEX = re.compile('.*FATAL EXCEPTION.*:') |
| 29 |
| 30 ANDROID_JOB_TYPE_MARKER = 'android' |
| 31 DEFAULT_TOP_N_FRAMES = 7 |
| 32 |
| 33 CALLSTACK_FLAG_GROUP = 'callstack_flags' |
| 34 STACKTRACE_FLAG_GROUP = 'stacktrace_flags' |
| 35 |
| 36 SANITIZER_TO_CALLSTACK_DETECTOR_CLASS = { |
| 37 SanitizerType.SYZYASAN: callstack_detectors.SyzyasanDetector, |
| 38 SanitizerType.THREAD_SANITIZER: callstack_detectors.TsanDetector, |
| 39 SanitizerType.UBSAN: callstack_detectors.UbsanDetector, |
| 40 SanitizerType.MEMORY_SANITIZER: callstack_detectors.MsanDetector, |
| 41 SanitizerType.ADDRESS_SANITIZER: callstack_detectors.AsanDetector |
| 42 } |
| 43 |
| 44 |
| 45 def GetCallStackDetector(job_type, sanitizer): |
| 46 """Returns a ``CallStackDetector`` for particular sanitizer and job type.""" |
| 47 if ANDROID_JOB_TYPE_MARKER in job_type: |
| 48 return callstack_detectors.AndroidJobDetector() |
| 49 |
| 50 try: |
| 51 return SANITIZER_TO_CALLSTACK_DETECTOR_CLASS[sanitizer]() |
| 52 except KeyError: |
| 53 return None |
| 54 |
| 55 |
| 56 class ClusterfuzzParser(StacktraceParser): |
| 57 |
| 58 def __init__(self): |
| 59 self.flag_manager = FlagManager() |
| 60 self.flag_manager.Register(STACKTRACE_FLAG_GROUP, ParsingFlag( |
| 61 'java_main_stack', lambda line: # pylint: disable=W0108 |
| 62 JAVA_FATAL_EXCEPTION_REGEX.match(line))) |
| 63 self.flag_manager.Register(STACKTRACE_FLAG_GROUP, ParsingFlag( |
| 64 'after_summary_line', lambda line: # pylint: disable=W0108 |
| 65 SUMMARY_MARKER in line)) |
| 66 # This flag is True at the very beginning and will never be changed once it |
| 67 # is set to False. |
| 68 self.flag_manager.Register(STACKTRACE_FLAG_GROUP, ParsingFlag( |
| 69 'is_first_stack', |
| 70 lambda line: False, value=True)) # pylint: disable=W0108 |
| 71 self.flag_manager.Register(CALLSTACK_FLAG_GROUP, ParsingFlag( |
| 72 'top_frame_has_no_symbol', lambda line: # pylint: disable=W0108 |
| 73 TOP_FRAME_HAS_NO_SYMBOLS_REGEX.match(line))) |
| 74 |
| 75 def UpdateMetadataWithFlags(self, stack_buffer): |
| 76 """Updates metadata with callstack flags. Returns updated stack buffer.""" |
| 77 for flag in self.flag_manager.GetGroupFlags(CALLSTACK_FLAG_GROUP): |
| 78 stack_buffer.metadata[flag.name] = flag.value |
| 79 return stack_buffer |
| 80 |
| 81 def Parse(self, stacktrace_string, deps, job_type, # pylint: disable=W0221 |
| 82 signature=None, top_n_frames=None, |
| 83 crash_address=None): |
| 84 """Parse clusterfuzz stacktrace string into Stacktrace instance.""" |
| 85 filters = [FilterJavaJreSdkFrames(), |
| 86 KeepV8FramesIfV8GeneratedJITCrash(), |
| 87 FilterV8FramesForV8APIBindingCode(crash_address), |
| 88 FilterFramesAfterBlinkGeneratedCode(), |
| 89 FilterV8FramesIfV8NotInTopFrames(), |
| 90 KeepTopNFrames(top_n_frames or DEFAULT_TOP_N_FRAMES)] |
| 91 sanitizer = SanitizerType.GetSanitizerType(job_type, stacktrace_string) |
| 92 stacktrace_buffer = StacktraceBuffer(signature=signature, filters=filters) |
| 93 |
| 94 stack_detector = GetCallStackDetector(job_type, sanitizer) |
| 95 if stack_detector is None: |
| 96 logging.error('Cannot find CallStackDetector for crash %s (job type: %s)', |
| 97 signature or '', job_type) |
| 98 return None |
| 99 |
| 100 # Initial background callstack which is not to be added into Stacktrace. |
| 101 stack_buffer = CallStackBuffer() |
| 102 # Reset both stacktrace and callstack flags. |
| 103 self.flag_manager.ResetAllFlags() |
| 104 for line in stacktrace_string.splitlines(): |
| 105 # Note, some flags like is_first_stack may be changed inside of stack |
| 106 # detector. |
| 107 is_new_callstack, priority, format_type, language_type, metadata = ( |
| 108 stack_detector.IsStartOfNewCallStack(line, flags=self.flag_manager)) |
| 109 |
| 110 if is_new_callstack: |
| 111 stacktrace_buffer.AddFilteredStack( |
| 112 self.UpdateMetadataWithFlags(stack_buffer)) |
| 113 |
| 114 # Create new stack and reset callstack scope flags. |
| 115 stack_buffer = CallStackBuffer(priority=priority, |
| 116 format_type=format_type, |
| 117 language_type=language_type, |
| 118 metadata=metadata) |
| 119 self.flag_manager.ResetGroupFlags(CALLSTACK_FLAG_GROUP) |
| 120 else: |
| 121 frame = StackFrame.Parse(stack_buffer.language_type, |
| 122 stack_buffer.format_type, line, deps, |
| 123 len(stack_buffer.frames)) |
| 124 if frame is not None: |
| 125 stack_buffer.frames.append(frame) |
| 126 # Turn on flags if condition met. |
| 127 self.flag_manager.ConditionallyTurnOnFlags(line) |
| 128 |
| 129 # Add the last stack to stacktrace. |
| 130 stacktrace_buffer.AddFilteredStack( |
| 131 self.UpdateMetadataWithFlags(stack_buffer)) |
| 132 return stacktrace_buffer.ToStacktrace() |
| OLD | NEW |