mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
Fix memory access violations triggered by running addr2line on fuzzed binaries.
PR binutils/17512 * dwarf.c (read_1_byte, read_1_signed_byte, read_2_bytes) (read_4_bytes, read_8_bytes, read_n_bytes, read_string) (read_indirect_string, read_alt_indirect_string) (read_alt_indirect_ref, read_address, read_abbrevs) (read_attribute_value, read_attribute, decode_line_info) (find_abstract_instance_name, read_rangelist) (scan_unit_for_symbols, parse_comp_unit) (_bfd_dwarf2_find_nearest_line): Harden DWARF reading code. Pass end pointers to reading functions and check for offsets taking pointers out of range. Replace calls to read_*_leb128 with calls to safe_read_leb128. (* elf64-ppc.c (opd_entry_value): Add a check for an overlarge offset. * syms.c (_bfd_stab_section_find_nearest_line): Add checks for computed file_name address being before the start of the string table.
This commit is contained in:
parent
0e7f931f3a
commit
dbb3fbbb1a
@ -1,3 +1,24 @@
|
||||
2015-02-12 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR binutils/17512
|
||||
* dwarf.c (read_1_byte, read_1_signed_byte, read_2_bytes)
|
||||
(read_4_bytes, read_8_bytes, read_n_bytes, read_string)
|
||||
(read_indirect_string, read_alt_indirect_string)
|
||||
(read_alt_indirect_ref, read_address, read_abbrevs)
|
||||
(read_attribute_value, read_attribute, decode_line_info)
|
||||
(find_abstract_instance_name, read_rangelist)
|
||||
(scan_unit_for_symbols, parse_comp_unit)
|
||||
(_bfd_dwarf2_find_nearest_line): Harden DWARF reading code. Pass
|
||||
end pointers to reading functions and check for offsets taking
|
||||
pointers out of range. Replace calls to read_*_leb128 with calls
|
||||
to safe_read_leb128.
|
||||
|
||||
(* elf64-ppc.c (opd_entry_value): Add a check for an overlarge
|
||||
offset.
|
||||
* syms.c (_bfd_stab_section_find_nearest_line): Add checks for
|
||||
computed file_name address being before the start of the string
|
||||
table.
|
||||
|
||||
2015-02-11 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/17878
|
||||
|
414
bfd/dwarf2.c
414
bfd/dwarf2.c
@ -556,83 +556,124 @@ read_section (bfd * abfd,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* VERBATIM
|
||||
The following function up to the END VERBATIM mark are
|
||||
copied directly from dwarf2read.c. */
|
||||
|
||||
/* Read dwarf information from a buffer. */
|
||||
|
||||
static unsigned int
|
||||
read_1_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf)
|
||||
read_1_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf, bfd_byte *end)
|
||||
{
|
||||
if (buf + 1 > end)
|
||||
return 0;
|
||||
return bfd_get_8 (abfd, buf);
|
||||
}
|
||||
|
||||
static int
|
||||
read_1_signed_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf)
|
||||
read_1_signed_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf, bfd_byte *end)
|
||||
{
|
||||
if (buf + 1 > end)
|
||||
return 0;
|
||||
return bfd_get_signed_8 (abfd, buf);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
read_2_bytes (bfd *abfd, bfd_byte *buf)
|
||||
read_2_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
|
||||
{
|
||||
if (buf + 2 > end)
|
||||
return 0;
|
||||
return bfd_get_16 (abfd, buf);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
read_4_bytes (bfd *abfd, bfd_byte *buf)
|
||||
read_4_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
|
||||
{
|
||||
if (buf + 4 > end)
|
||||
return 0;
|
||||
return bfd_get_32 (abfd, buf);
|
||||
}
|
||||
|
||||
static bfd_uint64_t
|
||||
read_8_bytes (bfd *abfd, bfd_byte *buf)
|
||||
read_8_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
|
||||
{
|
||||
if (buf + 8 > end)
|
||||
return 0;
|
||||
return bfd_get_64 (abfd, buf);
|
||||
}
|
||||
|
||||
static bfd_byte *
|
||||
read_n_bytes (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
bfd_byte *buf,
|
||||
bfd_byte *end,
|
||||
unsigned int size ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (buf + size > end)
|
||||
return NULL;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *
|
||||
read_string (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
bfd_byte *buf,
|
||||
unsigned int *bytes_read_ptr)
|
||||
{
|
||||
/* Return a pointer to the embedded string. */
|
||||
char *str = (char *) buf;
|
||||
/* Scans a NUL terminated string starting at BUF, returning a pointer to it.
|
||||
Returns the number of characters in the string, *including* the NUL byte,
|
||||
in BYTES_READ_PTR. This value is set even if the function fails. Bytes
|
||||
at or beyond BUF_END will not be read. Returns NULL if there was a
|
||||
problem, or if the string is empty. */
|
||||
|
||||
if (*str == '\0')
|
||||
static char *
|
||||
read_string (bfd * abfd ATTRIBUTE_UNUSED,
|
||||
bfd_byte * buf,
|
||||
bfd_byte * buf_end,
|
||||
unsigned int * bytes_read_ptr)
|
||||
{
|
||||
bfd_byte *str = buf;
|
||||
|
||||
if (buf >= buf_end)
|
||||
{
|
||||
*bytes_read_ptr = 1;
|
||||
* bytes_read_ptr = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*bytes_read_ptr = strlen (str) + 1;
|
||||
return str;
|
||||
if (*str == '\0')
|
||||
{
|
||||
* bytes_read_ptr = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (buf < buf_end)
|
||||
if (* buf ++ == 0)
|
||||
{
|
||||
* bytes_read_ptr = buf - str;
|
||||
return (char *) str;
|
||||
}
|
||||
|
||||
* bytes_read_ptr = buf - str;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* END VERBATIM */
|
||||
/* Reads an offset from BUF and then locates the string at this offset
|
||||
inside the debug string section. Returns a pointer to the string.
|
||||
Returns the number of bytes read from BUF, *not* the length of the string,
|
||||
in BYTES_READ_PTR. This value is set even if the function fails. Bytes
|
||||
at or beyond BUF_END will not be read from BUF. Returns NULL if there was
|
||||
a problem, or if the string is empty. Does not check for NUL termination
|
||||
of the string. */
|
||||
|
||||
static char *
|
||||
read_indirect_string (struct comp_unit * unit,
|
||||
bfd_byte * buf,
|
||||
bfd_byte * buf_end,
|
||||
unsigned int * bytes_read_ptr)
|
||||
{
|
||||
bfd_uint64_t offset;
|
||||
struct dwarf2_debug *stash = unit->stash;
|
||||
char *str;
|
||||
|
||||
if (buf + unit->offset_size > buf_end)
|
||||
{
|
||||
* bytes_read_ptr = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (unit->offset_size == 4)
|
||||
offset = read_4_bytes (unit->abfd, buf);
|
||||
offset = read_4_bytes (unit->abfd, buf, buf_end);
|
||||
else
|
||||
offset = read_8_bytes (unit->abfd, buf);
|
||||
offset = read_8_bytes (unit->abfd, buf, buf_end);
|
||||
|
||||
*bytes_read_ptr = unit->offset_size;
|
||||
|
||||
@ -641,6 +682,8 @@ read_indirect_string (struct comp_unit * unit,
|
||||
&stash->dwarf_str_buffer, &stash->dwarf_str_size))
|
||||
return NULL;
|
||||
|
||||
if (offset >= stash->dwarf_str_size)
|
||||
return NULL;
|
||||
str = (char *) stash->dwarf_str_buffer + offset;
|
||||
if (*str == '\0')
|
||||
return NULL;
|
||||
@ -654,16 +697,23 @@ read_indirect_string (struct comp_unit * unit,
|
||||
static char *
|
||||
read_alt_indirect_string (struct comp_unit * unit,
|
||||
bfd_byte * buf,
|
||||
bfd_byte * buf_end,
|
||||
unsigned int * bytes_read_ptr)
|
||||
{
|
||||
bfd_uint64_t offset;
|
||||
struct dwarf2_debug *stash = unit->stash;
|
||||
char *str;
|
||||
|
||||
if (buf + unit->offset_size > buf_end)
|
||||
{
|
||||
* bytes_read_ptr = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (unit->offset_size == 4)
|
||||
offset = read_4_bytes (unit->abfd, buf);
|
||||
offset = read_4_bytes (unit->abfd, buf, buf_end);
|
||||
else
|
||||
offset = read_8_bytes (unit->abfd, buf);
|
||||
offset = read_8_bytes (unit->abfd, buf, buf_end);
|
||||
|
||||
*bytes_read_ptr = unit->offset_size;
|
||||
|
||||
@ -696,6 +746,8 @@ read_alt_indirect_string (struct comp_unit * unit,
|
||||
&stash->alt_dwarf_str_size))
|
||||
return NULL;
|
||||
|
||||
if (offset >= stash->alt_dwarf_str_size)
|
||||
return NULL;
|
||||
str = (char *) stash->alt_dwarf_str_buffer + offset;
|
||||
if (*str == '\0')
|
||||
return NULL;
|
||||
@ -742,17 +794,22 @@ read_alt_indirect_ref (struct comp_unit * unit,
|
||||
&stash->alt_dwarf_info_size))
|
||||
return NULL;
|
||||
|
||||
if (offset >= stash->alt_dwarf_info_size)
|
||||
return NULL;
|
||||
return stash->alt_dwarf_info_buffer + offset;
|
||||
}
|
||||
|
||||
static bfd_uint64_t
|
||||
read_address (struct comp_unit *unit, bfd_byte *buf)
|
||||
read_address (struct comp_unit *unit, bfd_byte *buf, bfd_byte * buf_end)
|
||||
{
|
||||
int signed_vma = 0;
|
||||
|
||||
if (bfd_get_flavour (unit->abfd) == bfd_target_elf_flavour)
|
||||
signed_vma = get_elf_backend_data (unit->abfd)->sign_extend_vma;
|
||||
|
||||
if (buf + unit->addr_size > buf_end)
|
||||
return 0;
|
||||
|
||||
if (signed_vma)
|
||||
{
|
||||
switch (unit->addr_size)
|
||||
@ -815,6 +872,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
|
||||
{
|
||||
struct abbrev_info **abbrevs;
|
||||
bfd_byte *abbrev_ptr;
|
||||
bfd_byte *abbrev_end;
|
||||
struct abbrev_info *cur_abbrev;
|
||||
unsigned int abbrev_number, bytes_read, abbrev_name;
|
||||
unsigned int abbrev_form, hash_number;
|
||||
@ -825,13 +883,17 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
|
||||
&stash->dwarf_abbrev_buffer, &stash->dwarf_abbrev_size))
|
||||
return NULL;
|
||||
|
||||
if (offset >= stash->dwarf_abbrev_size)
|
||||
return NULL;
|
||||
|
||||
amt = sizeof (struct abbrev_info*) * ABBREV_HASH_SIZE;
|
||||
abbrevs = (struct abbrev_info **) bfd_zalloc (abfd, amt);
|
||||
if (abbrevs == NULL)
|
||||
return NULL;
|
||||
|
||||
abbrev_ptr = stash->dwarf_abbrev_buffer + offset;
|
||||
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_end = stash->dwarf_abbrev_buffer + stash->dwarf_abbrev_size;
|
||||
abbrev_number = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
|
||||
abbrev_ptr += bytes_read;
|
||||
|
||||
/* Loop until we reach an abbrev number of 0. */
|
||||
@ -845,15 +907,15 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
|
||||
/* Read in abbrev header. */
|
||||
cur_abbrev->number = abbrev_number;
|
||||
cur_abbrev->tag = (enum dwarf_tag)
|
||||
read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
|
||||
abbrev_ptr += bytes_read;
|
||||
cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
|
||||
cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr, abbrev_end);
|
||||
abbrev_ptr += 1;
|
||||
|
||||
/* Now read in declarations. */
|
||||
abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_name = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
|
||||
abbrev_ptr += bytes_read;
|
||||
abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_form = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
|
||||
abbrev_ptr += bytes_read;
|
||||
|
||||
while (abbrev_name)
|
||||
@ -888,9 +950,9 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
|
||||
= (enum dwarf_attribute) abbrev_name;
|
||||
cur_abbrev->attrs[cur_abbrev->num_attrs++].form
|
||||
= (enum dwarf_form) abbrev_form;
|
||||
abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_name = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
|
||||
abbrev_ptr += bytes_read;
|
||||
abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_form = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
|
||||
abbrev_ptr += bytes_read;
|
||||
}
|
||||
|
||||
@ -908,9 +970,9 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
|
||||
if ((unsigned int) (abbrev_ptr - stash->dwarf_abbrev_buffer)
|
||||
>= stash->dwarf_abbrev_size)
|
||||
break;
|
||||
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
||||
abbrev_number = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
|
||||
abbrev_ptr += bytes_read;
|
||||
if (lookup_abbrev (abbrev_number,abbrevs) != NULL)
|
||||
if (lookup_abbrev (abbrev_number, abbrevs) != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -925,19 +987,29 @@ is_str_attr (enum dwarf_form form)
|
||||
return form == DW_FORM_string || form == DW_FORM_strp || form == DW_FORM_GNU_strp_alt;
|
||||
}
|
||||
|
||||
/* Read an attribute value described by an attribute form. */
|
||||
/* Read and fill in the value of attribute ATTR as described by FORM.
|
||||
Read data starting from INFO_PTR, but never at or beyond INFO_PTR_END.
|
||||
Returns an updated INFO_PTR taking into account the amount of data read. */
|
||||
|
||||
static bfd_byte *
|
||||
read_attribute_value (struct attribute *attr,
|
||||
unsigned form,
|
||||
struct comp_unit *unit,
|
||||
bfd_byte *info_ptr)
|
||||
read_attribute_value (struct attribute * attr,
|
||||
unsigned form,
|
||||
struct comp_unit * unit,
|
||||
bfd_byte * info_ptr,
|
||||
bfd_byte * info_ptr_end)
|
||||
{
|
||||
bfd *abfd = unit->abfd;
|
||||
unsigned int bytes_read;
|
||||
struct dwarf_block *blk;
|
||||
bfd_size_type amt;
|
||||
|
||||
if (info_ptr >= info_ptr_end)
|
||||
{
|
||||
(*_bfd_error_handler) (_("Dwarf Error: Info pointer extends beyond end of attributes"));
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return info_ptr;
|
||||
}
|
||||
|
||||
attr->form = (enum dwarf_form) form;
|
||||
|
||||
switch (form)
|
||||
@ -948,23 +1020,23 @@ read_attribute_value (struct attribute *attr,
|
||||
if (unit->version == 3 || unit->version == 4)
|
||||
{
|
||||
if (unit->offset_size == 4)
|
||||
attr->u.val = read_4_bytes (unit->abfd, info_ptr);
|
||||
attr->u.val = read_4_bytes (unit->abfd, info_ptr, info_ptr_end);
|
||||
else
|
||||
attr->u.val = read_8_bytes (unit->abfd, info_ptr);
|
||||
attr->u.val = read_8_bytes (unit->abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += unit->offset_size;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case DW_FORM_addr:
|
||||
attr->u.val = read_address (unit, info_ptr);
|
||||
attr->u.val = read_address (unit, info_ptr, info_ptr_end);
|
||||
info_ptr += unit->addr_size;
|
||||
break;
|
||||
case DW_FORM_GNU_ref_alt:
|
||||
case DW_FORM_sec_offset:
|
||||
if (unit->offset_size == 4)
|
||||
attr->u.val = read_4_bytes (unit->abfd, info_ptr);
|
||||
attr->u.val = read_4_bytes (unit->abfd, info_ptr, info_ptr_end);
|
||||
else
|
||||
attr->u.val = read_8_bytes (unit->abfd, info_ptr);
|
||||
attr->u.val = read_8_bytes (unit->abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += unit->offset_size;
|
||||
break;
|
||||
case DW_FORM_block2:
|
||||
@ -972,9 +1044,9 @@ read_attribute_value (struct attribute *attr,
|
||||
blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
|
||||
if (blk == NULL)
|
||||
return NULL;
|
||||
blk->size = read_2_bytes (abfd, info_ptr);
|
||||
blk->size = read_2_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 2;
|
||||
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
|
||||
blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
|
||||
info_ptr += blk->size;
|
||||
attr->u.blk = blk;
|
||||
break;
|
||||
@ -983,34 +1055,34 @@ read_attribute_value (struct attribute *attr,
|
||||
blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
|
||||
if (blk == NULL)
|
||||
return NULL;
|
||||
blk->size = read_4_bytes (abfd, info_ptr);
|
||||
blk->size = read_4_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 4;
|
||||
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
|
||||
blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
|
||||
info_ptr += blk->size;
|
||||
attr->u.blk = blk;
|
||||
break;
|
||||
case DW_FORM_data2:
|
||||
attr->u.val = read_2_bytes (abfd, info_ptr);
|
||||
attr->u.val = read_2_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 2;
|
||||
break;
|
||||
case DW_FORM_data4:
|
||||
attr->u.val = read_4_bytes (abfd, info_ptr);
|
||||
attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 4;
|
||||
break;
|
||||
case DW_FORM_data8:
|
||||
attr->u.val = read_8_bytes (abfd, info_ptr);
|
||||
attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 8;
|
||||
break;
|
||||
case DW_FORM_string:
|
||||
attr->u.str = read_string (abfd, info_ptr, &bytes_read);
|
||||
attr->u.str = read_string (abfd, info_ptr, info_ptr_end, &bytes_read);
|
||||
info_ptr += bytes_read;
|
||||
break;
|
||||
case DW_FORM_strp:
|
||||
attr->u.str = read_indirect_string (unit, info_ptr, &bytes_read);
|
||||
attr->u.str = read_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read);
|
||||
info_ptr += bytes_read;
|
||||
break;
|
||||
case DW_FORM_GNU_strp_alt:
|
||||
attr->u.str = read_alt_indirect_string (unit, info_ptr, &bytes_read);
|
||||
attr->u.str = read_alt_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read);
|
||||
info_ptr += bytes_read;
|
||||
break;
|
||||
case DW_FORM_exprloc:
|
||||
@ -1019,9 +1091,9 @@ read_attribute_value (struct attribute *attr,
|
||||
blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
|
||||
if (blk == NULL)
|
||||
return NULL;
|
||||
blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
||||
blk->size = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
|
||||
info_ptr += bytes_read;
|
||||
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
|
||||
blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
|
||||
info_ptr += blk->size;
|
||||
attr->u.blk = blk;
|
||||
break;
|
||||
@ -1030,59 +1102,59 @@ read_attribute_value (struct attribute *attr,
|
||||
blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
|
||||
if (blk == NULL)
|
||||
return NULL;
|
||||
blk->size = read_1_byte (abfd, info_ptr);
|
||||
blk->size = read_1_byte (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 1;
|
||||
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
|
||||
blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
|
||||
info_ptr += blk->size;
|
||||
attr->u.blk = blk;
|
||||
break;
|
||||
case DW_FORM_data1:
|
||||
attr->u.val = read_1_byte (abfd, info_ptr);
|
||||
attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 1;
|
||||
break;
|
||||
case DW_FORM_flag:
|
||||
attr->u.val = read_1_byte (abfd, info_ptr);
|
||||
attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 1;
|
||||
break;
|
||||
case DW_FORM_flag_present:
|
||||
attr->u.val = 1;
|
||||
break;
|
||||
case DW_FORM_sdata:
|
||||
attr->u.sval = read_signed_leb128 (abfd, info_ptr, &bytes_read);
|
||||
attr->u.sval = safe_read_leb128 (abfd, info_ptr, &bytes_read, TRUE, info_ptr_end);
|
||||
info_ptr += bytes_read;
|
||||
break;
|
||||
case DW_FORM_udata:
|
||||
attr->u.val = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
||||
attr->u.val = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
|
||||
info_ptr += bytes_read;
|
||||
break;
|
||||
case DW_FORM_ref1:
|
||||
attr->u.val = read_1_byte (abfd, info_ptr);
|
||||
attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 1;
|
||||
break;
|
||||
case DW_FORM_ref2:
|
||||
attr->u.val = read_2_bytes (abfd, info_ptr);
|
||||
attr->u.val = read_2_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 2;
|
||||
break;
|
||||
case DW_FORM_ref4:
|
||||
attr->u.val = read_4_bytes (abfd, info_ptr);
|
||||
attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 4;
|
||||
break;
|
||||
case DW_FORM_ref8:
|
||||
attr->u.val = read_8_bytes (abfd, info_ptr);
|
||||
attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 8;
|
||||
break;
|
||||
case DW_FORM_ref_sig8:
|
||||
attr->u.val = read_8_bytes (abfd, info_ptr);
|
||||
attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end);
|
||||
info_ptr += 8;
|
||||
break;
|
||||
case DW_FORM_ref_udata:
|
||||
attr->u.val = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
||||
attr->u.val = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
|
||||
info_ptr += bytes_read;
|
||||
break;
|
||||
case DW_FORM_indirect:
|
||||
form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
||||
form = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
|
||||
info_ptr += bytes_read;
|
||||
info_ptr = read_attribute_value (attr, form, unit, info_ptr);
|
||||
info_ptr = read_attribute_value (attr, form, unit, info_ptr, info_ptr_end);
|
||||
break;
|
||||
default:
|
||||
(*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %#x."),
|
||||
@ -1096,13 +1168,14 @@ read_attribute_value (struct attribute *attr,
|
||||
/* Read an attribute described by an abbreviated attribute. */
|
||||
|
||||
static bfd_byte *
|
||||
read_attribute (struct attribute *attr,
|
||||
struct attr_abbrev *abbrev,
|
||||
struct comp_unit *unit,
|
||||
bfd_byte *info_ptr)
|
||||
read_attribute (struct attribute * attr,
|
||||
struct attr_abbrev * abbrev,
|
||||
struct comp_unit * unit,
|
||||
bfd_byte * info_ptr,
|
||||
bfd_byte * info_ptr_end)
|
||||
{
|
||||
attr->name = abbrev->name;
|
||||
info_ptr = read_attribute_value (attr, abbrev->form, unit, info_ptr);
|
||||
info_ptr = read_attribute_value (attr, abbrev->form, unit, info_ptr, info_ptr_end);
|
||||
return info_ptr;
|
||||
}
|
||||
|
||||
@ -1388,6 +1461,8 @@ concat_filename (struct line_info_table *table, unsigned int file)
|
||||
size_t len;
|
||||
|
||||
if (table->files[file - 1].dir
|
||||
/* PR 17512: file: 0317e960. */
|
||||
&& table->files[file - 1].dir <= table->num_dirs
|
||||
/* PR 17512: file: 7f3d2e4b. */
|
||||
&& table->dirs != NULL)
|
||||
subdir_name = table->dirs[table->files[file - 1].dir - 1];
|
||||
@ -1610,27 +1685,47 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
|
||||
table->lcl_head = NULL;
|
||||
|
||||
if (stash->dwarf_line_size < 16)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("Dwarf Error: Line info section is too small (%ld)"),
|
||||
(long) stash->dwarf_line_size);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return NULL;
|
||||
}
|
||||
line_ptr = stash->dwarf_line_buffer + unit->line_offset;
|
||||
line_end = stash->dwarf_line_buffer + stash->dwarf_line_size;
|
||||
|
||||
/* Read in the prologue. */
|
||||
lh.total_length = read_4_bytes (abfd, line_ptr);
|
||||
lh.total_length = read_4_bytes (abfd, line_ptr, line_end);
|
||||
line_ptr += 4;
|
||||
offset_size = 4;
|
||||
if (lh.total_length == 0xffffffff)
|
||||
{
|
||||
lh.total_length = read_8_bytes (abfd, line_ptr);
|
||||
lh.total_length = read_8_bytes (abfd, line_ptr, line_end);
|
||||
line_ptr += 8;
|
||||
offset_size = 8;
|
||||
}
|
||||
else if (lh.total_length == 0 && unit->addr_size == 8)
|
||||
{
|
||||
/* Handle (non-standard) 64-bit DWARF2 formats. */
|
||||
lh.total_length = read_4_bytes (abfd, line_ptr);
|
||||
lh.total_length = read_4_bytes (abfd, line_ptr, line_end);
|
||||
line_ptr += 4;
|
||||
offset_size = 8;
|
||||
}
|
||||
|
||||
if (lh.total_length > stash->dwarf_line_size)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("Dwarf Error: Line info data is bigger (0x%lx) than the section (0x%lx)"),
|
||||
(long) lh.total_length, (long) stash->dwarf_line_size);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line_end = line_ptr + lh.total_length;
|
||||
lh.version = read_2_bytes (abfd, line_ptr);
|
||||
|
||||
lh.version = read_2_bytes (abfd, line_ptr, line_end);
|
||||
if (lh.version < 2 || lh.version > 4)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
@ -1639,20 +1734,32 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
return NULL;
|
||||
}
|
||||
line_ptr += 2;
|
||||
|
||||
if (line_ptr + offset_size + (lh.version >=4 ? 6 : 5) >= line_end)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("Dwarf Error: Ran out of room reading prologue"));
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (offset_size == 4)
|
||||
lh.prologue_length = read_4_bytes (abfd, line_ptr);
|
||||
lh.prologue_length = read_4_bytes (abfd, line_ptr, line_end);
|
||||
else
|
||||
lh.prologue_length = read_8_bytes (abfd, line_ptr);
|
||||
lh.prologue_length = read_8_bytes (abfd, line_ptr, line_end);
|
||||
line_ptr += offset_size;
|
||||
lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
|
||||
|
||||
lh.minimum_instruction_length = read_1_byte (abfd, line_ptr, line_end);
|
||||
line_ptr += 1;
|
||||
|
||||
if (lh.version >= 4)
|
||||
{
|
||||
lh.maximum_ops_per_insn = read_1_byte (abfd, line_ptr);
|
||||
lh.maximum_ops_per_insn = read_1_byte (abfd, line_ptr, line_end);
|
||||
line_ptr += 1;
|
||||
}
|
||||
else
|
||||
lh.maximum_ops_per_insn = 1;
|
||||
|
||||
if (lh.maximum_ops_per_insn == 0)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
@ -1660,14 +1767,26 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return NULL;
|
||||
}
|
||||
lh.default_is_stmt = read_1_byte (abfd, line_ptr);
|
||||
|
||||
lh.default_is_stmt = read_1_byte (abfd, line_ptr, line_end);
|
||||
line_ptr += 1;
|
||||
lh.line_base = read_1_signed_byte (abfd, line_ptr);
|
||||
|
||||
lh.line_base = read_1_signed_byte (abfd, line_ptr, line_end);
|
||||
line_ptr += 1;
|
||||
lh.line_range = read_1_byte (abfd, line_ptr);
|
||||
|
||||
lh.line_range = read_1_byte (abfd, line_ptr, line_end);
|
||||
line_ptr += 1;
|
||||
lh.opcode_base = read_1_byte (abfd, line_ptr);
|
||||
|
||||
lh.opcode_base = read_1_byte (abfd, line_ptr, line_end);
|
||||
line_ptr += 1;
|
||||
|
||||
if (line_ptr + (lh.opcode_base - 1) >= line_end)
|
||||
{
|
||||
(*_bfd_error_handler) (_("Dwarf Error: Ran out of room reading opcodes"));
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
amt = lh.opcode_base * sizeof (unsigned char);
|
||||
lh.standard_opcode_lengths = (unsigned char *) bfd_alloc (abfd, amt);
|
||||
|
||||
@ -1675,12 +1794,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
|
||||
for (i = 1; i < lh.opcode_base; ++i)
|
||||
{
|
||||
lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
|
||||
lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr, line_end);
|
||||
line_ptr += 1;
|
||||
}
|
||||
|
||||
/* Read directory table. */
|
||||
while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
|
||||
while ((cur_dir = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL)
|
||||
{
|
||||
line_ptr += bytes_read;
|
||||
|
||||
@ -1703,7 +1822,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
line_ptr += bytes_read;
|
||||
|
||||
/* Read file name table. */
|
||||
while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
|
||||
while ((cur_file = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL)
|
||||
{
|
||||
line_ptr += bytes_read;
|
||||
|
||||
@ -1722,13 +1841,11 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
|
||||
table->files[table->num_files].name = cur_file;
|
||||
table->files[table->num_files].dir =
|
||||
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
table->files[table->num_files].time =
|
||||
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
table->files[table->num_files].time = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
table->files[table->num_files].size =
|
||||
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
table->files[table->num_files].size = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
table->num_files++;
|
||||
}
|
||||
@ -1758,13 +1875,15 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
/* Decode the table. */
|
||||
while (! end_sequence)
|
||||
{
|
||||
op_code = read_1_byte (abfd, line_ptr);
|
||||
op_code = read_1_byte (abfd, line_ptr, line_end);
|
||||
line_ptr += 1;
|
||||
|
||||
if (op_code >= lh.opcode_base)
|
||||
{
|
||||
/* Special operand. */
|
||||
adj_opcode = op_code - lh.opcode_base;
|
||||
if (lh.line_range == 0)
|
||||
goto line_fail;
|
||||
if (lh.maximum_ops_per_insn == 1)
|
||||
address += (adj_opcode / lh.line_range
|
||||
* lh.minimum_instruction_length);
|
||||
@ -1790,9 +1909,9 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
else switch (op_code)
|
||||
{
|
||||
case DW_LNS_extended_op:
|
||||
exop_len = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
exop_len = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
extended_op = read_1_byte (abfd, line_ptr);
|
||||
extended_op = read_1_byte (abfd, line_ptr, line_end);
|
||||
line_ptr += 1;
|
||||
|
||||
switch (extended_op)
|
||||
@ -1811,12 +1930,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
goto line_fail;
|
||||
break;
|
||||
case DW_LNE_set_address:
|
||||
address = read_address (unit, line_ptr);
|
||||
address = read_address (unit, line_ptr, line_end);
|
||||
op_index = 0;
|
||||
line_ptr += unit->addr_size;
|
||||
break;
|
||||
case DW_LNE_define_file:
|
||||
cur_file = read_string (abfd, line_ptr, &bytes_read);
|
||||
cur_file = read_string (abfd, line_ptr, line_end, &bytes_read);
|
||||
line_ptr += bytes_read;
|
||||
if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
|
||||
{
|
||||
@ -1831,19 +1950,19 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
}
|
||||
table->files[table->num_files].name = cur_file;
|
||||
table->files[table->num_files].dir =
|
||||
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
table->files[table->num_files].time =
|
||||
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
table->files[table->num_files].size =
|
||||
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
table->num_files++;
|
||||
break;
|
||||
case DW_LNE_set_discriminator:
|
||||
discriminator =
|
||||
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
break;
|
||||
case DW_LNE_HP_source_file_correlation:
|
||||
@ -1872,12 +1991,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
case DW_LNS_advance_pc:
|
||||
if (lh.maximum_ops_per_insn == 1)
|
||||
address += (lh.minimum_instruction_length
|
||||
* read_unsigned_leb128 (abfd, line_ptr,
|
||||
&bytes_read));
|
||||
* safe_read_leb128 (abfd, line_ptr, &bytes_read,
|
||||
FALSE, line_end));
|
||||
else
|
||||
{
|
||||
bfd_vma adjust = read_unsigned_leb128 (abfd, line_ptr,
|
||||
&bytes_read);
|
||||
bfd_vma adjust = safe_read_leb128 (abfd, line_ptr, &bytes_read,
|
||||
FALSE, line_end);
|
||||
address = ((op_index + adjust) / lh.maximum_ops_per_insn
|
||||
* lh.minimum_instruction_length);
|
||||
op_index = (op_index + adjust) % lh.maximum_ops_per_insn;
|
||||
@ -1885,7 +2004,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
line_ptr += bytes_read;
|
||||
break;
|
||||
case DW_LNS_advance_line:
|
||||
line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
|
||||
line += safe_read_leb128 (abfd, line_ptr, &bytes_read, TRUE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
break;
|
||||
case DW_LNS_set_file:
|
||||
@ -1894,7 +2013,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
|
||||
/* The file and directory tables are 0
|
||||
based, the references are 1 based. */
|
||||
file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
file = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
if (filename)
|
||||
free (filename);
|
||||
@ -1902,7 +2021,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
break;
|
||||
}
|
||||
case DW_LNS_set_column:
|
||||
column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
column = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
break;
|
||||
case DW_LNS_negate_stmt:
|
||||
@ -1924,7 +2043,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
}
|
||||
break;
|
||||
case DW_LNS_fixed_advance_pc:
|
||||
address += read_2_bytes (abfd, line_ptr);
|
||||
address += read_2_bytes (abfd, line_ptr, line_end);
|
||||
op_index = 0;
|
||||
line_ptr += 2;
|
||||
break;
|
||||
@ -1932,7 +2051,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
|
||||
/* Unknown standard opcode, ignore it. */
|
||||
for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
|
||||
{
|
||||
(void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
||||
(void) safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
|
||||
line_ptr += bytes_read;
|
||||
}
|
||||
break;
|
||||
@ -2161,6 +2280,7 @@ find_abstract_instance_name (struct comp_unit *unit,
|
||||
{
|
||||
bfd *abfd = unit->abfd;
|
||||
bfd_byte *info_ptr;
|
||||
bfd_byte *info_ptr_end;
|
||||
unsigned int abbrev_number, bytes_read, i;
|
||||
struct abbrev_info *abbrev;
|
||||
bfd_uint64_t die_ref = attr_ptr->u.val;
|
||||
@ -2177,6 +2297,7 @@ find_abstract_instance_name (struct comp_unit *unit,
|
||||
abort ();
|
||||
|
||||
info_ptr = unit->sec_info_ptr + die_ref;
|
||||
info_ptr_end = unit->end_ptr;
|
||||
|
||||
/* Now find the CU containing this pointer. */
|
||||
if (info_ptr >= unit->info_ptr_unit && info_ptr < unit->end_ptr)
|
||||
@ -2210,13 +2331,18 @@ find_abstract_instance_name (struct comp_unit *unit,
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return NULL;
|
||||
}
|
||||
info_ptr_end = unit->stash->alt_dwarf_info_buffer + unit->stash->alt_dwarf_info_size;
|
||||
|
||||
/* FIXME: Do we need to locate the correct CU, in a similar
|
||||
fashion to the code in the DW_FORM_ref_addr case above ? */
|
||||
}
|
||||
else
|
||||
info_ptr = unit->info_ptr_unit + die_ref;
|
||||
{
|
||||
info_ptr = unit->info_ptr_unit + die_ref;
|
||||
info_ptr_end = unit->end_ptr;
|
||||
}
|
||||
|
||||
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
||||
abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
|
||||
info_ptr += bytes_read;
|
||||
|
||||
if (abbrev_number)
|
||||
@ -2233,7 +2359,7 @@ find_abstract_instance_name (struct comp_unit *unit,
|
||||
for (i = 0; i < abbrev->num_attrs; ++i)
|
||||
{
|
||||
info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit,
|
||||
info_ptr);
|
||||
info_ptr, info_ptr_end);
|
||||
if (info_ptr == NULL)
|
||||
break;
|
||||
switch (attr.name)
|
||||
@ -2275,6 +2401,7 @@ read_rangelist (struct comp_unit *unit, struct arange *arange,
|
||||
bfd_uint64_t offset)
|
||||
{
|
||||
bfd_byte *ranges_ptr;
|
||||
bfd_byte *ranges_end;
|
||||
bfd_vma base_address = unit->base_address;
|
||||
|
||||
if (! unit->stash->dwarf_ranges_buffer)
|
||||
@ -2282,16 +2409,24 @@ read_rangelist (struct comp_unit *unit, struct arange *arange,
|
||||
if (! read_debug_ranges (unit))
|
||||
return FALSE;
|
||||
}
|
||||
ranges_ptr = unit->stash->dwarf_ranges_buffer + offset;
|
||||
|
||||
ranges_ptr = unit->stash->dwarf_ranges_buffer + offset;
|
||||
if (ranges_ptr < unit->stash->dwarf_ranges_buffer)
|
||||
return FALSE;
|
||||
ranges_end = unit->stash->dwarf_ranges_buffer + unit->stash->dwarf_ranges_size;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
bfd_vma low_pc;
|
||||
bfd_vma high_pc;
|
||||
|
||||
low_pc = read_address (unit, ranges_ptr);
|
||||
/* PR 17512: file: 62cada7d. */
|
||||
if (ranges_ptr + 2 * unit->addr_size >= ranges_end)
|
||||
return FALSE;
|
||||
|
||||
low_pc = read_address (unit, ranges_ptr, ranges_end);
|
||||
ranges_ptr += unit->addr_size;
|
||||
high_pc = read_address (unit, ranges_ptr);
|
||||
high_pc = read_address (unit, ranges_ptr, ranges_end);
|
||||
ranges_ptr += unit->addr_size;
|
||||
|
||||
if (low_pc == 0 && high_pc == 0)
|
||||
@ -2318,6 +2453,7 @@ 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 = 1;
|
||||
struct funcinfo **nested_funcs;
|
||||
int nested_funcs_size;
|
||||
@ -2343,10 +2479,10 @@ scan_unit_for_symbols (struct comp_unit *unit)
|
||||
bfd_boolean high_pc_relative = FALSE;
|
||||
|
||||
/* PR 17512: file: 9f405d9d. */
|
||||
if (info_ptr >= unit->stash->info_ptr_end)
|
||||
if (info_ptr >= info_ptr_end)
|
||||
goto fail;
|
||||
|
||||
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
||||
abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
|
||||
info_ptr += bytes_read;
|
||||
|
||||
if (! abbrev_number)
|
||||
@ -2410,7 +2546,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
|
||||
|
||||
for (i = 0; i < abbrev->num_attrs; ++i)
|
||||
{
|
||||
info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
|
||||
info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, info_ptr_end);
|
||||
if (info_ptr == NULL)
|
||||
goto fail;
|
||||
|
||||
@ -2608,15 +2744,15 @@ parse_comp_unit (struct dwarf2_debug *stash,
|
||||
bfd *abfd = stash->bfd_ptr;
|
||||
bfd_boolean high_pc_relative = FALSE;
|
||||
|
||||
version = read_2_bytes (abfd, info_ptr);
|
||||
version = read_2_bytes (abfd, info_ptr, end_ptr);
|
||||
info_ptr += 2;
|
||||
BFD_ASSERT (offset_size == 4 || offset_size == 8);
|
||||
if (offset_size == 4)
|
||||
abbrev_offset = read_4_bytes (abfd, info_ptr);
|
||||
abbrev_offset = read_4_bytes (abfd, info_ptr, end_ptr);
|
||||
else
|
||||
abbrev_offset = read_8_bytes (abfd, info_ptr);
|
||||
abbrev_offset = read_8_bytes (abfd, info_ptr, end_ptr);
|
||||
info_ptr += offset_size;
|
||||
addr_size = read_1_byte (abfd, info_ptr);
|
||||
addr_size = read_1_byte (abfd, info_ptr, end_ptr);
|
||||
info_ptr += 1;
|
||||
|
||||
if (version != 2 && version != 3 && version != 4)
|
||||
@ -2653,7 +2789,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
|
||||
if (! abbrevs)
|
||||
return 0;
|
||||
|
||||
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
||||
abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, end_ptr);
|
||||
info_ptr += bytes_read;
|
||||
if (! abbrev_number)
|
||||
{
|
||||
@ -2688,7 +2824,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
|
||||
|
||||
for (i = 0; i < abbrev->num_attrs; ++i)
|
||||
{
|
||||
info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
|
||||
info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, end_ptr);
|
||||
if (info_ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -3838,13 +3974,13 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
|
||||
unsigned int offset_size = addr_size;
|
||||
bfd_byte *info_ptr_unit = stash->info_ptr;
|
||||
|
||||
length = read_4_bytes (stash->bfd_ptr, stash->info_ptr);
|
||||
length = read_4_bytes (stash->bfd_ptr, stash->info_ptr, stash->info_ptr_end);
|
||||
/* A 0xffffff length is the DWARF3 way of indicating
|
||||
we use 64-bit offsets, instead of 32-bit offsets. */
|
||||
if (length == 0xffffffff)
|
||||
{
|
||||
offset_size = 8;
|
||||
length = read_8_bytes (stash->bfd_ptr, stash->info_ptr + 4);
|
||||
length = read_8_bytes (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
|
||||
stash->info_ptr += 12;
|
||||
}
|
||||
/* A zero length is the IRIX way of indicating 64-bit offsets,
|
||||
@ -3853,7 +3989,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
|
||||
else if (length == 0)
|
||||
{
|
||||
offset_size = 8;
|
||||
length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4);
|
||||
length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
|
||||
stash->info_ptr += 8;
|
||||
}
|
||||
/* In the absence of the hints above, we assume 32-bit DWARF2
|
||||
@ -3875,14 +4011,26 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
bfd_byte * new_ptr;
|
||||
|
||||
each = parse_comp_unit (stash, length, info_ptr_unit,
|
||||
offset_size);
|
||||
if (!each)
|
||||
/* The dwarf information is damaged, don't trust it any
|
||||
more. */
|
||||
break;
|
||||
stash->info_ptr += length;
|
||||
|
||||
new_ptr = stash->info_ptr + length;
|
||||
/* PR 17512: file: 1500698c. */
|
||||
if (new_ptr < stash->info_ptr)
|
||||
{
|
||||
/* A corrupt length value - do not trust the info any more. */
|
||||
found = FALSE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
stash->info_ptr = new_ptr;
|
||||
|
||||
if (stash->all_comp_units)
|
||||
stash->all_comp_units->prev_unit = each;
|
||||
else
|
||||
|
@ -5951,6 +5951,10 @@ opd_entry_value (asection *opd_sec,
|
||||
ppc64_elf_tdata (opd_bfd)->opd.contents = contents;
|
||||
}
|
||||
|
||||
/* PR 17512: file: 64b9dfbb. */
|
||||
if (offset > bfd_section_size (opd_bfd, opd_sec))
|
||||
return (bfd_vma) -1;
|
||||
|
||||
val = bfd_get_64 (opd_bfd, contents + offset);
|
||||
if (code_sec != NULL)
|
||||
{
|
||||
|
@ -1192,7 +1192,7 @@ _bfd_stab_section_find_nearest_line (bfd *abfd,
|
||||
{
|
||||
nul_fun = stab;
|
||||
nul_str = str;
|
||||
if (file_name >= (char *) info->strs + strsize)
|
||||
if (file_name >= (char *) info->strs + strsize || file_name < (char *) str)
|
||||
file_name = NULL;
|
||||
if (stab + STABSIZE + TYPEOFF < info->stabs + stabsize
|
||||
&& *(stab + STABSIZE + TYPEOFF) == (bfd_byte) N_SO)
|
||||
@ -1203,7 +1203,7 @@ _bfd_stab_section_find_nearest_line (bfd *abfd,
|
||||
directory_name = file_name;
|
||||
file_name = ((char *) str
|
||||
+ bfd_get_32 (abfd, stab + STRDXOFF));
|
||||
if (file_name >= (char *) info->strs + strsize)
|
||||
if (file_name >= (char *) info->strs + strsize || file_name < (char *) str)
|
||||
file_name = NULL;
|
||||
}
|
||||
}
|
||||
@ -1213,7 +1213,8 @@ _bfd_stab_section_find_nearest_line (bfd *abfd,
|
||||
/* The name of an include file. */
|
||||
file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF);
|
||||
/* PR 17512: file: 0c680a1f. */
|
||||
if (file_name >= (char *) info->strs + strsize)
|
||||
/* PR 17512: file: 5da8aec4. */
|
||||
if (file_name >= (char *) info->strs + strsize || file_name < (char *) str)
|
||||
file_name = NULL;
|
||||
break;
|
||||
|
||||
@ -1331,7 +1332,7 @@ _bfd_stab_section_find_nearest_line (bfd *abfd,
|
||||
if (val <= offset)
|
||||
{
|
||||
file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF);
|
||||
if (file_name >= (char *) info->strs + strsize)
|
||||
if (file_name >= (char *) info->strs + strsize || file_name < (char *) str)
|
||||
file_name = NULL;
|
||||
*pline = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user