aboutsummaryrefslogtreecommitdiff
path: root/bfd/dwarf2.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-11-30 09:12:29 +1030
committerAlan Modra <amodra@gmail.com>2019-12-03 16:05:40 +1030
commit019cc8758a68d016db920f96de3273a2824929d1 (patch)
tree0936437a5a17c7aea43823eb52fcb646de79e1b8 /bfd/dwarf2.c
parent1b8e12713b399450f8befc5f52442219f1f63669 (diff)
downloadgdb-019cc8758a68d016db920f96de3273a2824929d1.zip
gdb-019cc8758a68d016db920f96de3273a2824929d1.tar.gz
gdb-019cc8758a68d016db920f96de3273a2824929d1.tar.bz2
dwarf2.c: read_abbrevs fail cleanup, and offset checking
read_section does offset checking, reporting an error on out of bounds. There's no need to duplicate the check in functions calling read_section. Also, I spotted a place where a pointer difference expression was being cast to unsigned int, possibly truncating relevant bits on a 64-bit host. * dwarf2.c (read_indirect_string): Don't duplicate offset check done in read_section. (read_indirect_line_string): Likewise. (read_alt_indirect_string): Likewise. (read_alt_indirect_ref): Likewise. (read_abbrevs): Likewise. Free memory on all failure paths. Use correct unsigned type for pointer difference comparison.
Diffstat (limited to 'bfd/dwarf2.c')
-rw-r--r--bfd/dwarf2.c51
1 files changed, 22 insertions, 29 deletions
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index dd3a2fb..0d5d84e 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -721,8 +721,6 @@ 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;
@@ -760,8 +758,6 @@ read_indirect_line_string (struct comp_unit * unit,
&stash->dwarf_line_str_size))
return NULL;
- if (offset >= stash->dwarf_line_str_size)
- return NULL;
str = (char *) stash->dwarf_line_str_buffer + offset;
if (*str == '\0')
return NULL;
@@ -825,8 +821,6 @@ 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;
@@ -874,8 +868,6 @@ 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;
}
@@ -963,9 +955,6 @@ 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)
@@ -983,7 +972,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
amt = sizeof (struct abbrev_info);
cur_abbrev = (struct abbrev_info *) bfd_zalloc (abfd, amt);
if (cur_abbrev == NULL)
- return NULL;
+ goto fail;
/* Read in abbrev header. */
cur_abbrev->number = abbrev_number;
@@ -1025,21 +1014,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
amt *= sizeof (struct attr_abbrev);
tmp = (struct attr_abbrev *) bfd_realloc (cur_abbrev->attrs, amt);
if (tmp == NULL)
- {
- size_t i;
-
- for (i = 0; i < ABBREV_HASH_SIZE; i++)
- {
- struct abbrev_info *abbrev = abbrevs[i];
-
- while (abbrev)
- {
- free (abbrev->attrs);
- abbrev = abbrev->next;
- }
- }
- return NULL;
- }
+ goto fail;
cur_abbrev->attrs = tmp;
}
@@ -1063,7 +1038,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
already read (which means we are about to read the abbreviations
for the next compile unit) or if the end of the abbreviation
table is reached. */
- if ((unsigned int) (abbrev_ptr - stash->dwarf_abbrev_buffer)
+ if ((size_t) (abbrev_ptr - stash->dwarf_abbrev_buffer)
>= stash->dwarf_abbrev_size)
break;
abbrev_number = _bfd_safe_read_leb128 (abfd, abbrev_ptr,
@@ -1072,8 +1047,26 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
if (lookup_abbrev (abbrev_number, abbrevs) != NULL)
break;
}
-
return abbrevs;
+
+ fail:
+ if (abbrevs != NULL)
+ {
+ size_t i;
+
+ for (i = 0; i < ABBREV_HASH_SIZE; i++)
+ {
+ struct abbrev_info *abbrev = abbrevs[i];
+
+ while (abbrev)
+ {
+ free (abbrev->attrs);
+ abbrev = abbrev->next;
+ }
+ }
+ free (abbrevs);
+ }
+ return NULL;
}
/* Returns true if the form is one which has a string value. */