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

Side by Side Diff: tools/valgrind/asan/asan_symbolize.py

Issue 2818653003: Don't double-JSON-escape crash stacks in asan symbolizer. (Closed)
Patch Set: Created 3 years, 8 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 from third_party import asan_symbolize 7 from third_party import asan_symbolize
8 8
9 import argparse 9 import argparse
10 import base64 10 import base64
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 # is located in the product dir. 156 # is located in the product dir.
157 outermost_bundle = bundle_positions[0] 157 outermost_bundle = bundle_positions[0]
158 product_dir = path_parts[:outermost_bundle] 158 product_dir = path_parts[:outermost_bundle]
159 # In case 2 this is the same as |outermost_bundle|. 159 # In case 2 this is the same as |outermost_bundle|.
160 innermost_bundle = bundle_positions[-1] 160 innermost_bundle = bundle_positions[-1]
161 dsym_path = product_dir + [path_parts[innermost_bundle]] 161 dsym_path = product_dir + [path_parts[innermost_bundle]]
162 result = '%s.dSYM' % os.path.join(*dsym_path) 162 result = '%s.dSYM' % os.path.join(*dsym_path)
163 return [result] 163 return [result]
164 164
165 165
166 # We want our output to match base::EscapeJSONString(), which produces
167 # doubly-escaped strings. The first escaping pass is handled by this class. The
168 # second pass happens when JSON data is dumped to file.
169 class StringEncoder(json.JSONEncoder):
170 def __init__(self):
171 json.JSONEncoder.__init__(self)
172
173 def encode(self, s):
174 assert(isinstance(s, basestring))
175 # Don't die on invalid utf-8 sequences.
176 s = s.decode('utf-8', 'replace')
177 encoded = json.JSONEncoder.encode(self, s)
178 assert(len(encoded) >= 2)
179 assert(encoded[0] == '"')
180 assert(encoded[-1] == '"')
181 encoded = encoded[1:-1]
182 # Special case from base::EscapeJSONString().
183 encoded = encoded.replace('<', '\u003C')
184 return encoded
185
186
187 class JSONTestRunSymbolizer(object): 166 class JSONTestRunSymbolizer(object):
188 def __init__(self, symbolization_loop): 167 def __init__(self, symbolization_loop):
189 self.symbolization_loop = symbolization_loop 168 self.symbolization_loop = symbolization_loop
190 169
191 def symbolize_snippet(self, snippet): 170 def symbolize_snippet(self, snippet):
192 symbolized_lines = [] 171 symbolized_lines = []
193 for line in snippet.split('\n'): 172 for line in snippet.split('\n'):
194 symbolized_lines += self.symbolization_loop.process_line(line) 173 symbolized_lines += self.symbolization_loop.process_line(line)
195 return '\n'.join(symbolized_lines) 174 return '\n'.join(symbolized_lines)
196 175
197 def symbolize(self, test_run): 176 def symbolize(self, test_run):
198 original_snippet = base64.b64decode(test_run['output_snippet_base64']) 177 original_snippet = base64.b64decode(test_run['output_snippet_base64'])
199 symbolized_snippet = self.symbolize_snippet(original_snippet) 178 symbolized_snippet = self.symbolize_snippet(original_snippet)
200 if symbolized_snippet == original_snippet: 179 if symbolized_snippet == original_snippet:
201 # No sanitizer reports in snippet. 180 # No sanitizer reports in snippet.
202 return 181 return
203 182
204 test_run['original_output_snippet'] = test_run['output_snippet'] 183 test_run['original_output_snippet'] = test_run['output_snippet']
205 test_run['original_output_snippet_base64'] = \ 184 test_run['original_output_snippet_base64'] = \
206 test_run['output_snippet_base64'] 185 test_run['output_snippet_base64']
207 186
208 escaped_snippet = StringEncoder().encode(symbolized_snippet) 187 test_run['output_snippet'] = symbolized_snippet
209 test_run['output_snippet'] = escaped_snippet
210 test_run['output_snippet_base64'] = \ 188 test_run['output_snippet_base64'] = \
211 base64.b64encode(symbolized_snippet) 189 base64.b64encode(symbolized_snippet)
212 test_run['snippet_processed_by'] = 'asan_symbolize.py' 190 test_run['snippet_processed_by'] = 'asan_symbolize.py'
213 # Originally, "lossless" refers to "no Unicode data lost while encoding the
214 # string". However, since we're applying another kind of transformation
215 # (symbolization), it doesn't seem right to consider the snippet lossless.
216 test_run['losless_snippet'] = False
217 191
218 192
219 def symbolize_snippets_in_json(filename, symbolization_loop): 193 def symbolize_snippets_in_json(filename, symbolization_loop):
220 with open(filename, 'r') as f: 194 with open(filename, 'r') as f:
221 json_data = json.load(f) 195 json_data = json.load(f)
222 196
223 test_run_symbolizer = JSONTestRunSymbolizer(symbolization_loop) 197 test_run_symbolizer = JSONTestRunSymbolizer(symbolization_loop)
224 for iteration_data in json_data['per_iteration_data']: 198 for iteration_data in json_data['per_iteration_data']:
225 for test_name, test_runs in iteration_data.iteritems(): 199 for test_name, test_runs in iteration_data.iteritems():
226 for test_run in test_runs: 200 for test_run in test_runs:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 236
263 if args.test_summary_json_file: 237 if args.test_summary_json_file:
264 symbolize_snippets_in_json(args.test_summary_json_file, loop) 238 symbolize_snippets_in_json(args.test_summary_json_file, loop)
265 else: 239 else:
266 # Process stdin. 240 # Process stdin.
267 asan_symbolize.logfile = sys.stdin 241 asan_symbolize.logfile = sys.stdin
268 loop.process_logfile() 242 loop.process_logfile()
269 243
270 if __name__ == '__main__': 244 if __name__ == '__main__':
271 main() 245 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698