@@ -109,6 +109,10 @@ class Symbolizer:
109109 self .__html = False
110110 self .__last_access_address = None
111111 self .__last_access_tag = None
112+ self .__tag_dump = []
113+ self .__tag_dump_match_idx = None
114+ self .__matched_stack_uas = False
115+ self .__offsets = []
112116
113117 def enable_html (self , enable ):
114118 self .__html = enable
@@ -311,6 +315,34 @@ class Symbolizer:
311315 if match :
312316 self .__last_access_tag = int (match .group (2 ), 16 )
313317
318+ def process_tag_dump_line (self , line , ignore_tags = False ):
319+ m = re .match (r'.*?(0x[0-9a-f]+):' + '([ ]*[\[ ][0-9a-f][0-9a-f]\]?)' * 16 , line )
320+ if m is None :
321+ return False
322+ addr = m .group (1 )
323+ tags = m .group (* range (2 , 18 ))
324+ fault = [i for i , x in enumerate (tags ) if '[' in x ]
325+ if fault :
326+ self .__tag_dump_match_idx = len (self .__tag_dump ) + fault [0 ]
327+ self .__tag_dump .extend (int (x .strip (' [' ).rstrip ('] ' ), 16 ) for x in tags )
328+ return True
329+
330+ def finish_tag_dump (self ):
331+ if self .__matched_stack_uas or self .__tag_dump_match_idx is None :
332+ return
333+ for offset , size , local in sorted (self .__offsets , key = lambda x : abs (x [0 ])):
334+ idx = self .__tag_dump_match_idx - offset // 16
335+ if idx < 0 or idx > len (self .__tag_dump ):
336+ continue
337+ if self .__tag_dump [idx ] == self .__last_access_tag :
338+ self .print ('' )
339+ self .print ('Potentially referenced stack object:' )
340+ if offset > 0 :
341+ self .print (' %d bytes after a variable "%s" in stack frame of function "%s"' % (offset - size , local [2 ], local [0 ]))
342+ if offset < 0 :
343+ self .print (' %d bytes before a variable "%s" in stack frame of function "%s"' % (- offset , local [2 ], local [0 ]))
344+ self .print (' at %s' % (local [1 ],))
345+
314346 def process_stack_history (self , line , ignore_tags = False ):
315347 if self .__last_access_address is None or self .__last_access_tag is None :
316348 return
@@ -336,16 +368,18 @@ class Symbolizer:
336368 size = local [4 ]
337369 if frame_offset is None or size is None :
338370 continue
339- obj_offset = (self .__last_access_address - fp - frame_offset ) & fp_mask
340- if obj_offset >= size :
341- continue
371+ obj_offset = (self .__last_access_address & fp_mask ) - ((fp & fp_mask ) + frame_offset )
342372 tag_offset = local [5 ]
343373 if not ignore_tags and (tag_offset is None or base_tag ^ tag_offset != self .__last_access_tag ):
344374 continue
375+ if obj_offset < 0 or obj_offset >= size :
376+ self .__offsets .append ((obj_offset , size , local ))
377+ continue
345378 self .print ('' )
346379 self .print ('Potentially referenced stack object:' )
347380 self .print (' %d bytes inside a variable "%s" in stack frame of function "%s"' % (obj_offset , local [2 ], local [0 ]))
348381 self .print (' at %s' % (local [1 ],))
382+ self .__matched_stack_uas = True
349383 return True
350384 return False
351385
@@ -456,9 +490,18 @@ def main():
456490 sys .exit (1 )
457491 symbolizer .read_linkify (args .linkify )
458492
493+ tag_dump = False
459494 for line in sys .stdin :
460495 if sys .version_info .major < 3 :
461496 line = line .decode ('utf-8' )
497+ if tag_dump :
498+ tag_dump = symbolizer .process_tag_dump_line (line )
499+ if tag_dump :
500+ continue
501+ symbolizer .finish_tag_dump ()
502+ if 'Memory tags around the buggy address' in line :
503+ tag_dump = True
504+
462505 symbolizer .save_access_address (line )
463506 if symbolizer .process_stack_history (line , ignore_tags = args .ignore_tags ):
464507 continue
0 commit comments