summaryrefslogtreecommitdiff
path: root/deps/v8/tools/testrunner/testproc/stack_utils/stack_analyzer_util.py
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/tools/testrunner/testproc/stack_utils/stack_analyzer_util.py')
-rw-r--r--deps/v8/tools/testrunner/testproc/stack_utils/stack_analyzer_util.py107
1 files changed, 107 insertions, 0 deletions
diff --git a/deps/v8/tools/testrunner/testproc/stack_utils/stack_analyzer_util.py b/deps/v8/tools/testrunner/testproc/stack_utils/stack_analyzer_util.py
new file mode 100644
index 0000000000..1deaecc60e
--- /dev/null
+++ b/deps/v8/tools/testrunner/testproc/stack_utils/stack_analyzer_util.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python3
+# Copyright 2022 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import re
+import sys
+
+
+ANALYSIS_FAILURE_STATES = ['NULL', 'Unknown', '', None]
+STACKFRAME_REGEX = r'^#\d+.*'
+FILE_LOCATION_REGEX = r'.*\:\d+\:\d+$'
+
+
+def fake_clusterfuzz_imports(modules):
+ for module in modules:
+ sys.modules[module] = __import__('clusterfuzz_fakes')
+
+
+def pre_clusterfuzz_import():
+ local_path = os.path.dirname(os.path.abspath(__file__))
+ sys.path.append(local_path)
+
+ fake_clusterfuzz_imports([
+ 'clusterfuzz._internal.platforms.android',
+ 'clusterfuzz._internal.google_cloud_utils',
+ 'clusterfuzz._internal.config.local_config',
+ ])
+
+
+class CustomStackParser:
+
+ def __init__(self):
+ pre_clusterfuzz_import()
+
+ from clusterfuzz.stacktraces import StackParser, MAX_CRASH_STATE_FRAMES
+ from clusterfuzz.stacktraces import llvm_test_one_input_override
+ from clusterfuzz.stacktraces import constants
+
+ self.MAX_CRASH_STATE_FRAMES = MAX_CRASH_STATE_FRAMES
+ self.stack_parser = StackParser()
+ self.constants = constants
+ self.llvm_test_one_input_override = llvm_test_one_input_override
+
+ def analyze_crash(self, stderr):
+ try:
+ stderr_analysis = self.stack_parser.parse(stderr)
+ self.custom_analyzer(stderr_analysis)
+ return {
+ "crash_state": stderr_analysis.crash_state.strip(),
+ "crash_type": stderr_analysis.crash_type.strip(),
+ }
+ except Exception as e:
+ logging.info(e)
+ return {
+ "crash_state": "Unknown",
+ "crash_type": "Unknown",
+ }
+
+ def _extract_function_name(self, frame):
+ split_frame = frame.split()
+ start_loc = 1
+ end_loc = -1
+ if len(split_frame) > 2 and split_frame[2] == 'in':
+ start_loc = 3
+ split_frame = split_frame[start_loc:]
+ for idx, item in enumerate(split_frame):
+ # exclude file name and everything after it
+ if re.match(FILE_LOCATION_REGEX, item):
+ end_loc = idx
+ break
+ if end_loc != -1:
+ return ' '.join(split_frame[:end_loc])
+ return None
+
+ def _fallback_crash_state(self, stacktrace):
+ status = []
+ for line in [l.strip() for l in stacktrace.splitlines()]:
+ if re.match(STACKFRAME_REGEX, line):
+ frame = self._extract_function_name(line)
+ if not self.stack_parser.ignore_stack_frame(frame):
+ status.append(frame)
+ if len(status) >= self.MAX_CRASH_STATE_FRAMES:
+ break
+
+ return '\n'.join(status)
+
+ def custom_analyzer(self, crash_info):
+ if crash_info.crash_state in ANALYSIS_FAILURE_STATES:
+ fallback_state = self._fallback_crash_state(crash_info.crash_stacktrace)
+ crash_info.crash_state = fallback_state or crash_info.crash_state
+
+
+class EmptyStackParser:
+
+ def analyze_crash(self, stderr):
+ return {}
+
+
+def create_stack_parser():
+ try:
+ return CustomStackParser()
+ except ImportError as e:
+ logging.info(e)
+ return EmptyStackParser()