diff options
author | Nick Clifton <nickc@redhat.com> | 2019-08-23 10:37:51 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2019-08-23 10:37:51 +0100 |
commit | afc72f154d6c59367e2f1cdf3ead5035748e2b61 (patch) | |
tree | b311b122a3851be68233ef77c7371be61a0b0574 /binutils | |
parent | 1aa7f807d239dc32433e5f10840cdc8e80824c64 (diff) | |
download | gdb-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')
-rw-r--r-- | binutils/ChangeLog | 8 | ||||
-rw-r--r-- | binutils/dwarf.c | 70 |
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 |