aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--binutils/ChangeLog8
-rw-r--r--binutils/dwarf.c70
2 files changed, 48 insertions, 30 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 34f2dc0..e5b197a 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,11 @@
+2019-08-23 Nick Clifton <nickc@redhat.com>
+
+ 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.
+
2019-08-22 Nick Clifton <nickc@redhat.com>
PR 24921
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