aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2020-10-21 17:42:42 +0100
committerAndreas K. Hüttel <dilfridge@gentoo.org>2021-01-23 20:21:15 +0200
commit22ce2abc86a235b91d86f0a438c7763a8f199b29 (patch)
tree4ae266ad6c13171bd7fe7f1ea29bc488cae96def
parentgas: Reuse the input file entry in the file table (diff)
downloadbinutils-gdb-22ce2abc86a235b91d86f0a438c7763a8f199b29.tar.gz
binutils-gdb-22ce2abc86a235b91d86f0a438c7763a8f199b29.tar.bz2
binutils-gdb-22ce2abc86a235b91d86f0a438c7763a8f199b29.zip
Work around problem in DWARF decoding library which can result in attempts to read arbitrary bytes as if they were an LEB128 encoded value.
* dwarf.c (skip_attr_bytes): Accept DWARF versions higher than 4 when processing the DW_FORM_ref_addr form. Skip bytes in DW_FORM_block and DW_FORM_exprloc forms. Handle DW_FORM_indirect. (get_type_signedness): Allow a limited amount of recursion. Do not attempt to decode types that use the DW_FORM_ref_addr form. (read_and_display_attr_value): Do not attempt to decode types that use the DW_FORM_ref_addr form. (cherry picked from commit 596245135106b2a965d809e272dc7c758afdc98f) (cherry picked from commit e7c1a13eb8fcdbd389b75b6ce261b17f7947ad9d)
-rw-r--r--binutils/ChangeLog14
-rw-r--r--binutils/dwarf.c43
2 files changed, 39 insertions, 18 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 20a120e914..8703850dc5 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,6 +1,20 @@
2020-11-15 Mark Wielaard <mark@klomp.org>
Backport from the mainline:
+ 2020-10-21 Nick Clifton <nickc@redhat.com>
+
+ * dwarf.c (skip_attr_bytes): Accept DWARF versions higher than 4
+ when processing the DW_FORM_ref_addr form.
+ Skip bytes in DW_FORM_block and DW_FORM_exprloc forms.
+ Handle DW_FORM_indirect.
+ (get_type_signedness): Allow a limited amount of recursion.
+ Do not attempt to decode types that use the DW_FORM_ref_addr form.
+ (read_and_display_attr_value): Do not attempt to decode types
+ that use the DW_FORM_ref_addr form.
+
+2020-11-15 Mark Wielaard <mark@klomp.org>
+
+ Backport from the mainline:
2020-11-11 Bernd Edlinger <bernd.edlinger@hotmail.de>
* dwarf.c (display_debug_rnglists_list): Only bias the
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index e673c4b7fa..f55a81c833 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -1868,7 +1868,7 @@ skip_attr_bytes (unsigned long form,
case DW_FORM_ref_addr:
if (dwarf_version == 2)
SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
- else if (dwarf_version == 3 || dwarf_version == 4)
+ else if (dwarf_version > 2)
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
else
return NULL;
@@ -1920,6 +1920,7 @@ skip_attr_bytes (unsigned long form,
case DW_FORM_ref8:
case DW_FORM_data8:
+ case DW_FORM_ref_sig8:
data += 8;
break;
@@ -1934,6 +1935,7 @@ skip_attr_bytes (unsigned long form,
case DW_FORM_block:
case DW_FORM_exprloc:
READ_ULEB (uvalue, data, end);
+ data += uvalue;
break;
case DW_FORM_block1:
@@ -1951,12 +1953,12 @@ skip_attr_bytes (unsigned long form,
data += 4 + uvalue;
break;
- case DW_FORM_ref_sig8:
- data += 8;
- break;
-
case DW_FORM_indirect:
- /* FIXME: Handle this form. */
+ READ_ULEB (form, data, end);
+ if (form == DW_FORM_implicit_const)
+ SKIP_ULEB (data, end);
+ return skip_attr_bytes (form, data, end, pointer_size, offset_size, dwarf_version, value_return);
+
default:
return NULL;
}
@@ -1978,7 +1980,7 @@ get_type_signedness (unsigned char * start,
dwarf_vma offset_size,
int dwarf_version,
bfd_boolean * is_signed,
- bfd_boolean is_nested)
+ unsigned int nesting)
{
unsigned long abbrev_number;
abbrev_entry * entry;
@@ -1997,6 +1999,14 @@ get_type_signedness (unsigned char * start,
/* FIXME: Issue a warning ? */
return;
+#define MAX_NESTING 20
+ if (nesting > MAX_NESTING)
+ {
+ /* FIXME: Warn - or is this expected ?
+ NB/ We need to avoid infinite recursion. */
+ return;
+ }
+
for (attr = entry->first_attr;
attr != NULL && attr->attribute;
attr = attr->next)
@@ -2019,16 +2029,12 @@ get_type_signedness (unsigned char * start,
#endif
case DW_AT_type:
/* Recurse. */
- if (is_nested)
- {
- /* FIXME: Warn - or is this expected ?
- NB/ We need to avoid infinite recursion. */
- return;
- }
if (uvalue >= (size_t) (end - start))
return;
- get_type_signedness (start, start + uvalue, end, pointer_size,
- offset_size, dwarf_version, is_signed, TRUE);
+ /* We cannot correctly process DW_FORM_ref_addr at the moment. */
+ if (attr->form != DW_FORM_ref_addr)
+ get_type_signedness (start, start + uvalue, end, pointer_size,
+ offset_size, dwarf_version, is_signed, nesting + 1);
break;
case DW_AT_encoding:
@@ -2206,7 +2212,6 @@ read_and_display_attr_value (unsigned long attribute,
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
else
error (_("Internal error: DW_FORM_ref_addr is not supported in DWARF version 1.\n"));
-
break;
case DW_FORM_addr:
@@ -2663,8 +2668,10 @@ read_and_display_attr_value (unsigned long attribute,
{
bfd_boolean is_signed = FALSE;
- get_type_signedness (start, start + uvalue, end, pointer_size,
- offset_size, dwarf_version, & is_signed, FALSE);
+ /* We cannot correctly process DW_FORM_ref_addr at the moment. */
+ if (form != DW_FORM_ref_addr)
+ get_type_signedness (start, start + uvalue, end, pointer_size,
+ offset_size, dwarf_version, & is_signed, 0);
level_type_signed[level] = is_signed;
}
break;