aboutsummaryrefslogtreecommitdiff
path: root/binutils/dwarf.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2019-08-23 10:37:51 +0100
committerNick Clifton <nickc@redhat.com>2019-08-23 10:37:51 +0100
commitafc72f154d6c59367e2f1cdf3ead5035748e2b61 (patch)
treeb311b122a3851be68233ef77c7371be61a0b0574 /binutils/dwarf.c
parent1aa7f807d239dc32433e5f10840cdc8e80824c64 (diff)
downloadgdb-afc72f154d6c59367e2f1cdf3ead5035748e2b61.zip
gdb-afc72f154d6c59367e2f1cdf3ead5035748e2b61.tar.gz
gdb-afc72f154d6c59367e2f1cdf3ead5035748e2b61.tar.bz2
Prevent a potential illegal memory access in the DWARF parser when processing a corrupt file.
PR 24829 * dwarf.c (check_uvalue): New function. Ensures that a block's size is valid. (read_and_display_attr_value): Use check_value when processsing DW_FORM_block<n> attributes.
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r--binutils/dwarf.c70
1 files changed, 40 insertions, 30 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index b36406c..2768518 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -1832,6 +1832,34 @@ free_dwo_info (void)
first_dwo_info = NULL;
}
+/* Ensure that START + UVALUE is less than END.
+ Return an adjusted UVALUE if necessary to ensure this relationship. */
+
+static inline dwarf_vma
+check_uvalue (const unsigned char * start,
+ dwarf_vma uvalue,
+ const unsigned char * end)
+{
+ dwarf_vma max_uvalue = end - start;
+
+ /* FIXME: Testing "(start + uvalue) < start" miscompiles with gcc 4.8.3
+ running on an x86_64 host in 32-bit mode. So we pre-compute the value
+ here. */
+ const unsigned char * ptr = start + uvalue;
+
+ /* See PR 17512: file: 008-103549-0.001:0.1.
+ and PR 24829 for examples of where these tests are triggered. */
+ if (uvalue > max_uvalue
+ || ptr > end
+ || ptr < start)
+ {
+ warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
+ uvalue = max_uvalue;
+ }
+
+ return uvalue;
+}
+
static unsigned char *
read_and_display_attr_value (unsigned long attribute,
unsigned long form,
@@ -2056,16 +2084,9 @@ read_and_display_attr_value (unsigned long attribute,
uvalue = 0;
block_start = end;
}
- /* FIXME: Testing "(block_start + uvalue) < block_start" miscompiles with
- gcc 4.8.3 running on an x86_64 host in 32-bit mode. So we pre-compute
- block_start + uvalue here. */
- data = block_start + uvalue;
- /* PR 17512: file: 008-103549-0.001:0.1. */
- if (block_start + uvalue > end || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
+
+ uvalue = check_uvalue (block_start, uvalue, end);
+
if (do_loc)
data = block_start + uvalue;
else
@@ -2081,12 +2102,9 @@ read_and_display_attr_value (unsigned long attribute,
uvalue = 0;
block_start = end;
}
- data = block_start + uvalue;
- if (block_start + uvalue > end || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
+
+ uvalue = check_uvalue (block_start, uvalue, end);
+
if (do_loc)
data = block_start + uvalue;
else
@@ -2102,12 +2120,9 @@ read_and_display_attr_value (unsigned long attribute,
uvalue = 0;
block_start = end;
}
- data = block_start + uvalue;
- if (block_start + uvalue > end || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
+
+ uvalue = check_uvalue (block_start, uvalue, end);
+
if (do_loc)
data = block_start + uvalue;
else
@@ -2124,14 +2139,9 @@ read_and_display_attr_value (unsigned long attribute,
uvalue = 0;
block_start = end;
}
- data = block_start + uvalue;
- if (block_start + uvalue > end
- /* PR 17531: file: 5b5f0592. */
- || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
+
+ uvalue = check_uvalue (block_start, uvalue, end);
+
if (do_loc)
data = block_start + uvalue;
else