diff options
author | Alan Modra <amodra@gmail.com> | 2019-09-23 08:53:07 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2019-09-23 09:04:54 +0930 |
commit | b3fe587ed2c78d46132bd33e14f42449d410354b (patch) | |
tree | a7e3e2a9c209320816c2c587550fddaff1a50f6a /binutils | |
parent | a13ba30840ba7a8450dcb4edd356de61fcb89130 (diff) | |
download | gdb-b3fe587ed2c78d46132bd33e14f42449d410354b.zip gdb-b3fe587ed2c78d46132bd33e14f42449d410354b.tar.gz gdb-b3fe587ed2c78d46132bd33e14f42449d410354b.tar.bz2 |
PR25018, readelf crash on 32bits
Pointer comparisons after adding an offset just don't work to catch
overflow when the offset is a larger type than the pointer.
PR 25018
* dwarf.c (get_type_signedness): Delete ineffective pointer
comparison check. Properly range check uvalue offset on
recursive call.
(read_and_display_attr_value): Range check uvalue offset before
calling get_type_signedness.
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 9 | ||||
-rw-r--r-- | binutils/dwarf.c | 8 |
2 files changed, 13 insertions, 4 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 21dc92d..a2ac2b7 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,12 @@ +2019-09-23 Alan Modra <amodra@gmail.com> + + PR 25018 + * dwarf.c (get_type_signedness): Delete ineffective pointer + comparison check. Properly range check uvalue offset on + recursive call. + (read_and_display_attr_value): Range check uvalue offset before + calling get_type_signedness. + 2019-09-20 Alan Modra <amodra@gmail.com> * ar.c (write_archive): Use bfd_set_thin_archive. diff --git a/binutils/dwarf.c b/binutils/dwarf.c index df924e4..2fe469f 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -1999,9 +1999,6 @@ get_type_signedness (unsigned char * start, * is_signed = FALSE; - if (data >= end) - return; - abbrev_number = read_uleb128 (data, & bytes_read, end); data += bytes_read; @@ -2042,6 +2039,8 @@ get_type_signedness (unsigned char * start, 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); break; @@ -2725,7 +2724,8 @@ read_and_display_attr_value (unsigned long attribute, switch (attribute) { case DW_AT_type: - if (level >= 0 && level < MAX_CU_NESTING) + if (level >= 0 && level < MAX_CU_NESTING + && uvalue < (size_t) (end - start)) { bfd_boolean is_signed = FALSE; |