Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: appengine/findit/crash/callstack_filters.py

Issue 2588133003: [Predator] Add clusterfuzz callstack filters. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2016 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import re 5 import re
6 6
7 from crash.stacktrace import CallStack
8 from crash.type_enums import LanguageType
9
7 _INLINE_FUNCTION_FILE_PATH_MARKERS = [ 10 _INLINE_FUNCTION_FILE_PATH_MARKERS = [
8 'third_party/llvm-build/Release+Asserts/include/c++/v1/', 11 'third_party/llvm-build/Release+Asserts/include/c++/v1/',
9 'linux/debian_wheezy_amd64-sysroot/usr/include/c++/4.6/bits/', 12 'linux/debian_wheezy_amd64-sysroot/usr/include/c++/4.6/bits/',
10 'eglibc-3GlaMS/eglibc-2.19/sysdeps/unix/', 13 'eglibc-3GlaMS/eglibc-2.19/sysdeps/unix/',
11 ] 14 ]
12 15
16 # When checking the null pointer deference, any deference of a address within
wrengr 2016/12/19 23:51:05 "deference" -> "dereference" "a address" -> "an a
Sharu Jiang 2016/12/22 01:59:43 Done.
17 # the threshold is considered as null pointer deference. Be consistent with
wrengr 2016/12/19 23:51:05 ditto
Sharu Jiang 2016/12/22 01:59:43 Done.
18 # the threshold used in Clusterfuzz.
19 NULL_POINTER_DEREFERENCE_THRESHOLD = 4096
20 V8_JIT_CODE_MARKER = 'v8::internal::Invoke'
21 V8_API_H_FILE_PATH = 'src/api.h'
22 V8_API_CC_FILE_PATH = 'src/api.cc'
stgao 2016/12/20 19:07:36 Could we make a list instead of two separate files
Sharu Jiang 2016/12/22 01:59:43 Actually making it seperate would make the impleme
23 V8_DEP_PATH_MARKER = 'src/v8'
24 BLINK_BINDINGS_GENERATED_PATH_REGEX = re.compile(
25 r'out/[^/]+/gen/blink/bindings/.*')
26 JAVA_JRE_SDK_REGEX = re.compile(
27 r'(java\..*|javax\..*|org\.xml\..*|org\.w3c\..*|'
28 r'org\.omg\..*|org\.ietf\.jgss\..*)')
29
13 30
14 class CallStackFilter(object): 31 class CallStackFilter(object):
15 """Filters frames of a callstack buffer.""" 32 """Filters frames of a callstack buffer."""
16 33
17 def __call__(self, stack_buffer): 34 def __call__(self, stack_buffer):
18 """Returns the stack_buffer with frames filtered. 35 """Returns the stack_buffer with frames filtered.
19 36
20 Args: 37 Args:
21 stack_buffer (CallStackBuffer): stack buffer to be filtered. 38 stack_buffer (CallStackBuffer): stack buffer to be filtered.
22 """ 39 """
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 def __call__(self, stack_buffer): 72 def __call__(self, stack_buffer):
56 """Returns stack_buffer with only top n frames. 73 """Returns stack_buffer with only top n frames.
57 74
58 If no self.top_n_frames is None, don't do any filtering. 75 If no self.top_n_frames is None, don't do any filtering.
59 """ 76 """
60 if self.top_n_frames is None: 77 if self.top_n_frames is None:
61 return stack_buffer 78 return stack_buffer
62 79
63 stack_buffer.frames = stack_buffer.frames[:self.top_n_frames] 80 stack_buffer.frames = stack_buffer.frames[:self.top_n_frames]
64 return stack_buffer 81 return stack_buffer
82
83
84 class FilterJavaJreSdkFrames(CallStackFilter):
wrengr 2016/12/19 23:51:05 It's inconsistent to lowercase JRE and SDK here wh
Sharu Jiang 2016/12/22 01:59:43 This is because if it is ``FilterJavaJRESDKFrames`
wrengr 2016/12/22 23:31:51 yeah, JRESDK is hard to read too (though slightly
Sharu Jiang 2016/12/23 00:33:20 Ok... let's leave it as it is then.
85 """Filter out package names from Java JRE/SDK.
stgao 2016/12/20 19:07:36 nit: "Filter" -> "Filters" Same for other occurre
Sharu Jiang 2016/12/22 01:59:43 Done.
86
87 For example: java.*, javax.*, org.xml.*, org.w3c.*, org.omg.*,
88 org.ietf.jgss.*. These frames are misleading to Predator.
89 """
90 def __call__(self, stack_buffer):
91 if stack_buffer.language_type != LanguageType.JAVA:
92 return stack_buffer
93
94 stack_buffer.frames = filter(
95 lambda frame: not JAVA_JRE_SDK_REGEX.match(frame.function),
96 stack_buffer.frames)
97 return stack_buffer
98
99
100 class KeepV8FramesIfV8GeneratedJITCrash(CallStackFilter):
101 """Keeps v8 frames if conditions met.
102
103 If the top-most frames don't have symbols, but the top frame that does is
104 ``v8::internal::Invoke``, the bug is likely a crash in
105 V8's generated JIT code.
106 """
107 def __call__(self, stack_buffer):
108 if (stack_buffer and V8_JIT_CODE_MARKER in stack_buffer.frames[0].function
109 and stack_buffer.metadata.get('top_frame_has_no_symbols')):
110 stack_buffer.frames = filter(lambda f: V8_DEP_PATH_MARKER in f.dep_path,
111 stack_buffer.frames)
112 return stack_buffer
113
114
115 class FilterV8FramesForV8APIBindingCode(CallStackFilter):
116 """Filter all v8 frames if conditions met.
wrengr 2016/12/19 23:51:05 should clarify whether it's all conditions or any
Sharu Jiang 2016/12/22 01:59:43 Done.
117
118 Conditions:
119 (1) src/v8/src/api.h or src/v8/src/api.cc appears as
120 the top file in the stack trace.
121 (2) the second file is not in src/v8/src
122 (e.g. src/out/Release/gen/blink/bindings) or the crash is caused by
123 dereference of null pointer, then V8 should not be responsible for
124 the crash (likely a bindings issue).
stgao 2016/12/20 19:07:36 nit: Could we fill in the whole line before moving
Sharu Jiang 2016/12/22 01:59:43 Done.
125
126 Args:
127 crash_address: Address where crash happens.
wrengr 2016/12/19 23:51:05 type?
Sharu Jiang 2016/12/22 01:59:43 Done.
128
129 Returns:
stgao 2016/12/20 19:07:36 What is the Returns for? I'm confused here.
Sharu Jiang 2016/12/22 01:59:43 Oops, this should be removed.
130 A string of hint message.
131 """
132 def __init__(self, crash_address=None):
133 # Record the crash address of the to-be-parsed stack_buffer.
134 self.crash_address = crash_address
135
136 def __call__(self, stack_buffer):
137 if len(stack_buffer.frames) < 2:
138 return stack_buffer
139
140 first_frame_is_api_file = (
141 V8_DEP_PATH_MARKER in stack_buffer.frames[0].dep_path and
142 (V8_API_H_FILE_PATH == stack_buffer.frames[0].file_path or
143 V8_API_CC_FILE_PATH == stack_buffer.frames[0].file_path))
144
145 second_frame_not_from_v8_src = (
146 V8_DEP_PATH_MARKER not in stack_buffer.frames[1].dep_path or
147 not stack_buffer.frames[1].file_path.startswith('src'))
148
149 null_pointer_dereference = False
150 if self.crash_address:
151 try:
152 null_pointer_dereference = int(
153 self.crash_address,
154 base=16) < NULL_POINTER_DEREFERENCE_THRESHOLD
155 except ValueError: # pragma: no cover
156 # some testcases like memcpy-param-overlap have crash addresses like
157 # '[0x621000017d00,0x621000018cea) and [0x621000017d16, 0x621000018d00)'
158 pass
159
160 if (first_frame_is_api_file and (second_frame_not_from_v8_src or
161 null_pointer_dereference)):
162 stack_buffer.frames = filter(
163 lambda f: V8_DEP_PATH_MARKER not in f.dep_path,
164 stack_buffer.frames)
165 # After deleting all v8 frames, if the top n frames are generated code,
166 # need to filter them out.
167 top_n_generated_code_frames = 0
168 for frame in stack_buffer.frames:
169 if not BLINK_BINDINGS_GENERATED_PATH_REGEX.match(frame.file_path):
170 break
171 top_n_generated_code_frames += 1
172 stack_buffer.frames = stack_buffer.frames[top_n_generated_code_frames:]
173
174 return stack_buffer
175
176
177 class FilterFramesAfterBlinkGeneratedCode(CallStackFilter):
178 """Filter all the frames after blink generated code."""
179 def __call__(self, stack_buffer):
180 for index, frame in enumerate(stack_buffer):
181 if BLINK_BINDINGS_GENERATED_PATH_REGEX.match(frame.file_path):
182 stack_buffer.frames = stack_buffer.frames[:index]
183 break
stgao 2016/12/20 19:07:36 What if there are two frames with generated code?
Sharu Jiang 2016/12/22 01:59:43 This is to filter generated frames and frames afte
184
185 return stack_buffer
186
187
188 class FilterV8FramesIfV8NotInTopFrames(CallStackFilter):
189 """Filter all v8 frames if there is no v8 frames in top_n_frames."""
190 def __init__(self, top_n_frames=4):
191 self.top_n_frames = top_n_frames
192
193 def __call__(self, stack_buffer):
194 need_filter_v8 = False
195 for index, frame in enumerate(stack_buffer):
196 if index >= self.top_n_frames:
197 need_filter_v8 = True
198 break
199
200 if V8_DEP_PATH_MARKER in frame.dep_path:
201 break
202
203 if not need_filter_v8:
204 return stack_buffer
205
206 stack_buffer.frames = filter(
207 lambda f: not V8_DEP_PATH_MARKER in f.dep_path, stack_buffer.frames)
wrengr 2016/12/19 23:51:05 The syntax "x not in xs" is more standard than "no
Sharu Jiang 2016/12/22 01:59:43 Done.
208 return stack_buffer
OLDNEW
« no previous file with comments | « no previous file | appengine/findit/crash/stacktrace.py » ('j') | appengine/findit/crash/test/callstack_filters_test.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698