diff options
author | Alan Modra <amodra@gmail.com> | 2021-05-12 08:51:22 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2021-05-12 15:41:10 +0930 |
commit | 5ab3907543816d62a8dfd0f7f342ae66814bb0eb (patch) | |
tree | 2cb6e87bbfdf6d037ccb8f771269920ba830efaa /binutils/dwarf.c | |
parent | 425b0b1a98456359084466b755aad51c462603df (diff) | |
download | gdb-5ab3907543816d62a8dfd0f7f342ae66814bb0eb.zip gdb-5ab3907543816d62a8dfd0f7f342ae66814bb0eb.tar.gz gdb-5ab3907543816d62a8dfd0f7f342ae66814bb0eb.tar.bz2 |
PR27849, heap-buffer-overflow on readelf -w
PR 27849
* dwarf.c (fetch_indexed_string): Correct length sanity checks.
Sanity check section size for version and padding too. Correct
index sanity check. Handle multiple tables in .debug_str_offsets.
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r-- | binutils/dwarf.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 8bc0acb..336a3d5 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -745,7 +745,7 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set, dwarf_vma str_offset; const char * ret; unsigned char *curr = index_section->start; - const unsigned char *end = curr + index_section->size; + unsigned char *end = curr + index_section->size; dwarf_vma length; if (index_section->start == NULL) @@ -780,16 +780,31 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set, { /* Skip the version and padding bytes. We assume that they are correct. */ - curr += 4; + if (end - curr >= 4) + curr += 4; + else + curr = end; + if (length >= 4) + length -= 4; + else + length = 0; + + if (this_set != NULL + && this_set->section_sizes[DW_SECT_STR_OFFSETS] < length) + length = this_set->section_sizes[DW_SECT_STR_OFFSETS]; - /* FIXME: The code below assumes that there is only one table - in the .debug_str_offsets section, so check that now. */ - if ((offset_size == 4 && curr + length < (end - 8)) - || (offset_size == 8 && curr + length < (end - 16))) + if (length > (dwarf_vma) (end - curr)) { - warn (_("index table size is too small %s vs %s\n"), + warn (_("index table size too large for section %s vs %s\n"), dwarf_vmatoa ("x", length), dwarf_vmatoa ("x", index_section->size)); + length = end - curr; + } + + if (length < offset_size) + { + warn (_("index table size %s is too small\n"), + dwarf_vmatoa ("x", length)); return _("<table too small>"); } } @@ -799,7 +814,8 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set, if (this_set != NULL) index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS]; - if (index_offset >= length) + if (index_offset >= length + || length - index_offset < offset_size) { warn (_("DW_FORM_GNU_str_index offset too big: 0x%s vs 0x%s\n"), dwarf_vmatoa ("x", index_offset), |