parameters: (debugger, bad_access_info_vals, bad_access_info_frame,
                         from_uef)
return_statement: return corrupt_ranges
docstring: Extract the information stored in the minidump about the heap corruption.
  
    Args:
      debugger: A handle to a cdb debugging session.
      bad_access_info_vals: A dictionary containing the information about the
          invalid access.
      bad_access_info_frame: The number of the frame containing the error_info
          structure.
      from_uef: Indicates if the error has been caught by the unhandled exception
          filter.
  
    Returns:
      A list of corrupt ranges, each of them containing the information about the
      corrupt blocks in it.
docstring_summary: Extract the information stored in the minidump about the heap corruption.
docstring_tokens: Extract the information stored in the minidump about the heap corruption .
function: def GetCorruptHeapInfo(debugger, bad_access_info_vals, bad_access_info_frame,
                         from_uef):
    """Extract the information stored in the minidump about the heap corruption.
  
    Args:
      debugger: A handle to a cdb debugging session.
      bad_access_info_vals: A dictionary containing the information about the
          invalid access.
      bad_access_info_frame: The number of the frame containing the error_info
          structure.
      from_uef: Indicates if the error has been caught by the unhandled exception
          filter.
  
    Returns:
      A list of corrupt ranges, each of them containing the information about the
      corrupt blocks in it.
    """
    # Reset the debugger context and jump to the frame containing the information.
    corrupt_range_count = int(bad_access_info_vals['corrupt_range_count'], 16)
    debugger.Command('.cxr; .frame %X' % bad_access_info_frame)
  
    corrupt_ranges = []
  
    # Iterates over the corrupt ranges.
    for corrupt_range_idx in range(0, corrupt_range_count):
      corrupt_range_info = []
  
      # When using the '??' operator in a debugging session to evaluate a
      # structure the offsets gets printed, this regex allows their removal.
      struct_field_re = re.compile('\s+\+0x[0-9a-f]+\s*(.*)')
      operand = '.' if from_uef else '->'
  
      # Get the information about this corrupt range.
      for line in debugger.Command(
          '?? ((syzyasan_rtl!agent::asan::AsanCorruptBlockRange*)'
          '(error_info%scorrupt_ranges))[0x%x]' % (operand, corrupt_range_idx)):
        m = struct_field_re.match(line)
        if m:
          corrupt_range_info.append(m.group(1))
      corrupt_range_info_vals = DebugStructToDict(corrupt_range_info)
      block_info_count = int(corrupt_range_info_vals['block_info_count'])
      corrupt_range_info_vals['block_info'] = []
  
      # Iterates over the block info structure available for this range.
      for block_info_idx in range(0, block_info_count):
        # Retrieves the information about the current block info structure.
        block_info = []
        for line in debugger.Command(
            '?? ((syzyasan_rtl!agent::asan::AsanCorruptBlockRange*)'
            '(error_info%scorrupt_ranges))[%d].block_info[%d]' % (
                operand, corrupt_range_idx, block_info_idx)):
          m = struct_field_re.match(line)
          if m:
            block_info.append(m.group(1))
        block_info_corruption_state = []
        for line in debugger.Command(
            '?? ((syzyasan_rtl!agent::asan::AsanCorruptBlockRange*)'
            '(error_info%scorrupt_ranges))[%d].block_info[%d].analysis' % (
                operand, corrupt_range_idx, block_info_idx)):
          m = struct_field_re.match(line)
          if m:
            block_info_corruption_state.append(m.group(1))
        block_info_vals = DebugStructToDict(block_info)
        block_info_corruption_state_vals = DebugStructToDict(
            block_info_corruption_state)
        block_info_vals.pop('analysis', None)
        for e in block_info_corruption_state_vals:
          block_info_vals['analysis.%s' % e] = block_info_corruption_state_vals[e]
        # Get the allocation stack trace for this block info structure.
        block_info_vals['alloc_stack'], _ = NormalizeStackTrace(debugger.Command(
            _GET_CORRUPT_BLOCK_STACK_TRACE_TEMPLATE.format(type='alloc',
                operand=operand, range_idx=corrupt_range_idx,
                block_idx=block_info_idx)))
        # Get the free stack trace for this block info structure.
        block_info_vals['free_stack'], _ = NormalizeStackTrace(debugger.Command(
            _GET_CORRUPT_BLOCK_STACK_TRACE_TEMPLATE.format(type='free',
                operand=operand, range_idx=corrupt_range_idx,
                block_idx=block_info_idx)))
  
        # Get the block content.
        block_address = block_info_vals['header'].split(' ')[0]
        block_info_vals['block_content'] = []
        block_content = debugger.Command('db %s+0x10 L0x80' % block_address)
  
        # Match a block data line as printed by Windbg. This helps to get rid of
        # the extra characters that we sometime see at the beginning of the
        # lines ('0:000>').
        line_cleanup_re = re.compile('^\d\:\d+>\s*(.*)')
        for line in block_content:
          m = line_cleanup_re.match(line)
          if m:
            line = m.group(1)
          block_info_vals['block_content'].append(line)
  
        corrupt_range_info_vals['block_info'].append(block_info_vals)
  
      # Append the information about the current range to the list of corrupt
      # ranges.
      corrupt_ranges.append(corrupt_range_info_vals)
  
    return corrupt_ranges
function_tokens: def GetCorruptHeapInfo ( debugger , bad_access_info_vals , bad_access_info_frame , from_uef ) : # Reset the debugger context and jump to the frame containing the information. corrupt_range_count = int ( bad_access_info_vals [ 'corrupt_range_count' ] , 16 ) debugger . Command ( '.cxr; .frame %X' % bad_access_info_frame ) corrupt_ranges = [ ] # Iterates over the corrupt ranges. for corrupt_range_idx in range ( 0 , corrupt_range_count ) : corrupt_range_info = [ ] # When using the '??' operator in a debugging session to evaluate a # structure the offsets gets printed, this regex allows their removal. struct_field_re = re . compile ( '\s+\+0x[0-9a-f]+\s*(.*)' ) operand = '.' if from_uef else '->' # Get the information about this corrupt range. for line in debugger . Command ( '?? ((syzyasan_rtl!agent::asan::AsanCorruptBlockRange*)' '(error_info%scorrupt_ranges))[0x%x]' % ( operand , corrupt_range_idx ) ) : m = struct_field_re . match ( line ) if m : corrupt_range_info . append ( m . group ( 1 ) ) corrupt_range_info_vals = DebugStructToDict ( corrupt_range_info ) block_info_count = int ( corrupt_range_info_vals [ 'block_info_count' ] ) corrupt_range_info_vals [ 'block_info' ] = [ ] # Iterates over the block info structure available for this range. for block_info_idx in range ( 0 , block_info_count ) : # Retrieves the information about the current block info structure. block_info = [ ] for line in debugger . Command ( '?? ((syzyasan_rtl!agent::asan::AsanCorruptBlockRange*)' '(error_info%scorrupt_ranges))[%d].block_info[%d]' % ( operand , corrupt_range_idx , block_info_idx ) ) : m = struct_field_re . match ( line ) if m : block_info . append ( m . group ( 1 ) ) block_info_corruption_state = [ ] for line in debugger . Command ( '?? ((syzyasan_rtl!agent::asan::AsanCorruptBlockRange*)' '(error_info%scorrupt_ranges))[%d].block_info[%d].analysis' % ( operand , corrupt_range_idx , block_info_idx ) ) : m = struct_field_re . match ( line ) if m : block_info_corruption_state . append ( m . group ( 1 ) ) block_info_vals = DebugStructToDict ( block_info ) block_info_corruption_state_vals = DebugStructToDict ( block_info_corruption_state ) block_info_vals . pop ( 'analysis' , None ) for e in block_info_corruption_state_vals : block_info_vals [ 'analysis.%s' % e ] = block_info_corruption_state_vals [ e ] # Get the allocation stack trace for this block info structure. block_info_vals [ 'alloc_stack' ] , _ = NormalizeStackTrace ( debugger . Command ( _GET_CORRUPT_BLOCK_STACK_TRACE_TEMPLATE . format ( type = 'alloc' , operand = operand , range_idx = corrupt_range_idx , block_idx = block_info_idx ) ) ) # Get the free stack trace for this block info structure. block_info_vals [ 'free_stack' ] , _ = NormalizeStackTrace ( debugger . Command ( _GET_CORRUPT_BLOCK_STACK_TRACE_TEMPLATE . format ( type = 'free' , operand = operand , range_idx = corrupt_range_idx , block_idx = block_info_idx ) ) ) # Get the block content. block_address = block_info_vals [ 'header' ] . split ( ' ' ) [ 0 ] block_info_vals [ 'block_content' ] = [ ] block_content = debugger . Command ( 'db %s+0x10 L0x80' % block_address ) # Match a block data line as printed by Windbg. This helps to get rid of # the extra characters that we sometime see at the beginning of the # lines ('0:000>'). line_cleanup_re = re . compile ( '^\d\:\d+>\s*(.*)' ) for line in block_content : m = line_cleanup_re . match ( line ) if m : line = m . group ( 1 ) block_info_vals [ 'block_content' ] . append ( line ) corrupt_range_info_vals [ 'block_info' ] . append ( block_info_vals ) # Append the information about the current range to the list of corrupt # ranges. corrupt_ranges . append ( corrupt_range_info_vals ) return corrupt_ranges