aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-05-12 08:51:22 +0930
committerAlan Modra <amodra@gmail.com>2021-05-12 15:41:10 +0930
commit5ab3907543816d62a8dfd0f7f342ae66814bb0eb (patch)
tree2cb6e87bbfdf6d037ccb8f771269920ba830efaa /binutils
parent425b0b1a98456359084466b755aad51c462603df (diff)
downloadfsf-binutils-gdb-5ab3907543816d62a8dfd0f7f342ae66814bb0eb.zip
fsf-binutils-gdb-5ab3907543816d62a8dfd0f7f342ae66814bb0eb.tar.gz
fsf-binutils-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')
-rw-r--r--binutils/ChangeLog7
-rw-r--r--binutils/dwarf.c32
2 files changed, 31 insertions, 8 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 242563e..9e0611e 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,10 @@
+2021-05-12 Alan Modra <amodra@gmail.com>
+
+ 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.
+
2021-05-11 Hans-Peter Nilsson <hp@axis.com>
* dwarf.c (process_abbrev_set): Properly parenthesize before
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),