ZBLOG

static bfd_boolean scan_unit_for_symbols (struct comp_unit *unit) { bfd *abfd = unit->abfd; bfd_byte *info_ptr = unit->first_child_die_ptr; bfd_byte *info_ptr_end = unit->stash->info_ptr_end; int nesting_level = 0; struct nest_f

可能出现空指针漏洞的地方:

  1. 在读取属性时,info_ptr可能会超过info_ptr_end而变为NULL,在read_attribute函数中需要判断info_ptr是否为空指针。

  2. 在读取属性时,如果读到DW_AT_abstract_origin或DW_AT_specification属性,并且在find_abstract_instance函数中没有找到对应的DIE,则func->name、func->is_linkage、func->file和func->line这些指针都不会被赋值,这可能导致后续访问这些指针时出现空指针异常。

修改代码如下:

static bfd_boolean scan_unit_for_symbols (struct comp_unit *unit) { bfd *abfd = unit->abfd; bfd_byte *info_ptr = unit->first_child_die_ptr; bfd_byte *info_ptr_end = unit->stash->info_ptr_end; int nesting_level = 0; struct nest_funcinfo {

struct funcinfo *func;

} *nested_funcs; int nested_funcs_size;

/* Maintain a stack of in-scope functions and inlined functions, which we

 can use to set the caller_func field.  */

nested_funcs_size = 32; nested_funcs = (struct nest_funcinfo *)

bfd_malloc (nested_funcs_size * sizeof (*nested_funcs));

if (nested_funcs == NULL)

return FALSE;

nested_funcs[nesting_level].func = 0;

while (nesting_level >= 0)

{
  unsigned int abbrev_number, bytes_read, i;
  struct abbrev_info *abbrev;
  struct attribute attr;
  struct funcinfo *func = NULL;
  struct varinfo *var = NULL;
  bfd_vma low_pc = 0;
  bfd_vma high_pc = 0;
  bfd_boolean high_pc_relative = FALSE;

  /* PR 17512: file: 9f405d9d.  */
  if (info_ptr >= info_ptr_end)
goto fail;

  abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
				     FALSE, info_ptr_end);
  info_ptr += bytes_read;

  if (! abbrev_number)
{
  nesting_level--;
  continue;
}

  abbrev = lookup_abbrev (abbrev_number, unit->abbrevs);
  if (! abbrev)
{
  static unsigned int previous_failed_abbrev = -1U;

  /* Avoid multiple reports of the same missing abbrev.  */
  if (abbrev_number != previous_failed_abbrev)
    {
      _bfd_error_handler
	(_("DWARF error: could not find abbrev number %u"),
	 abbrev_number);
      previous_failed_abbrev = abbrev_number;
    }
  bfd_set_error (bfd_error_bad_value);
  goto fail;
}

  if (abbrev->tag == DW_TAG_subprogram
  || abbrev->tag == DW_TAG_entry_point
  || abbrev->tag == DW_TAG_inlined_subroutine)
{
  bfd_size_type amt = sizeof (struct funcinfo);
  func = (struct funcinfo *) bfd_zalloc (abfd, amt);
  if (func == NULL)
    goto fail;
  func->tag = abbrev->tag;
  func->prev_func = unit->function_table;
  unit->function_table = func;
  unit->number_of_functions++;
  BFD_ASSERT (!unit->cached);

  if (func->tag == DW_TAG_inlined_subroutine)
    for (i = nesting_level; i-- != 0; )
      if (nested_funcs[i].func)
	{
	  func->caller_func = nested_funcs[i].func;
	  break;
	}
  nested_funcs[nesting_level].func = func;
}
  else if (abbrev->tag == DW_TAG_variable)
{
  bfd_size_type amt = sizeof (struct varinfo);
  var = (struct varinfo *) bfd_zalloc (abfd, amt);
  if (var == NULL)
    goto fail;
  var->tag = abbrev->tag;
  var->stack = 1;
  var->prev_var = unit->variable_table;
  unit->variable_table = var;
}

  for (i = 0; i < abbrev->num_attrs; ++i)
{
  info_ptr = read_attribute (&attr, &abbrev->attrs[i],
			     unit, info_ptr, info_ptr_end);
  if (info_ptr == NULL)
    goto fail;

  if (func)
    {
      switch (attr.name)
	{
	case DW_AT_call_file:
	  func->caller_file = concat_filename (unit->line_table,
					       attr.u.val);
	  break;

	case DW_AT_call_line:
	  func->caller_line = attr.u.val;
	  break;

	case DW_AT_abstract_origin:
	case DW_AT_specification:
	  if (!find_abstract_instance (unit, info_ptr, &attr,
				       &func->name,
				       &func->is_linkage,
				       &func->file,
				       &func->line))
	    {
	      /* If find_abstract_instance failed, we need to free
	         the memory allocated for func. */
	      bfd_free(func);
	      func = NULL;
	      goto fail;
	    }
	  break;

	case DW_AT_name:
	  /* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
	     over DW_AT_name.  */
	  if (func->name == NULL && is_str_attr (attr.form))
	    {
	      func->name = attr.u.str;
	      if (non_mangled (unit->lang))
		func->is_linkage = TRUE;
	    }
	  break;

	case DW_AT_linkage_name:
	case DW_AT_MIPS_linkage_name:
	  /* PR 16949:  Corrupt debug info can place
	     non-string forms into these attributes.  */
	  if (is_str_attr (attr.form))
	    {
	      func->name = attr.u.str;
	      func->is_linkage = TRUE;
	    }
	  break;

	case DW_AT_low_pc:
	  low_pc = attr.u.val;
	  break;

	case DW_AT_high_pc:
	  high_pc = attr.u.val;
	  high_pc_relative = attr.form != DW_FORM_addr;
	  break;

	case DW_AT_ranges:
	  if (!read_rangelist (unit, &func->arange, attr.u.val))
	    {
	      bfd_free(func);
	      func = NULL;
	      goto fail;
	    }
	  break;

	case DW_AT_decl_file:
	  func->file = concat_filename (unit->line_table,
					attr.u.val);
	  break;

	case DW_AT_decl_line:
	  func->line = attr.u.val;
	  break;

	default:
	  break;
	}
    }
  else if (var)
    {
      switch (attr.name)
	{
	case DW_AT_name:
	  if (is_str_attr (attr.form))
	    var->name = attr.u.str;
	  break;

	case DW_AT_decl_file:
	  var->file = concat_filename (unit->line_table,
				       attr.u.val);
	  break;

	case DW_AT_decl_line:
	  var->line = attr.u.val;
	  break;

	case DW_AT_external:
	  if (attr.u.val != 0)
	    var->stack = 0;
	  break;

	case DW_AT_location:
	  switch (attr.form)
	    {
	    case DW_FORM_block:
	    case DW_FORM_block1:
	    case DW_FORM_block2:
	    case DW_FORM_block4:
	    case DW_FORM_exprloc:
	      if (attr.u.blk->data != NULL
		  && *attr.u.blk->data == DW_OP_addr)
		{
		  var->stack = 0;

		  /* Verify that DW_OP_addr is the only opcode in the
		     location, in which case the block size will be 1
		     plus the address size.  */
		  /* ??? For TLS variables, gcc can emit
		     DW_OP_addr <addr> DW_OP_GNU_push_tls_address
		     which we don't handle here yet.  */
		  if (attr.u.blk->size == unit->addr_size + 1U)
		    var->addr = bfd_get (unit->addr_size * 8,
					 unit->abfd,
					 attr.u.blk->data + 1);
		}
	      break;

	    default:
	      break;
	    }
	  break;

	default:
	  break;
	}
    }
}

  if (high_pc_relative)
high_pc += low_pc;

  if (func && high_pc != 0)
{
  if (!arange_add (unit, &func->arange, low_pc, high_pc))
    {
      bfd_free(func);
      func = NULL;
      goto fail;
    }
}

  if (abbrev->has_children)
{
  nesting_level++;

  if (nesting_level >= nested_funcs_size)
    {
      struct nest_funcinfo *tmp;

      nested_funcs_size *= 2;
      tmp = (struct nest_funcinfo *)
	bfd_realloc (nested_funcs,
		     nested_funcs_size * sizeof (*nested_funcs));
      if (tmp == NULL)
	{
	  bfd_free(func);
	  func = NULL;
	  goto fail;
	}
      nested_funcs = tmp;
    }
  nested_funcs[nesting_level].func = 0;
}
}

free (nested_funcs); return TRUE;

fail: free (nested_funcs); return FALSE; }

修改的地方:

  1. 在读取属性时,如果info_ptr为空指针,则跳转到fail标签。

  2. 在读取DW_AT_abstract_origin或DW_AT_specification属性后,如果find_abstract_instance函数返回FALSE,则需要释放已经分配的func内存,并跳转到fail标签。

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=194

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?