[binutils-gdb] PR25018, readelf crash on 32bits

Alan Modra amodra@sourceware.org
Sun Sep 22 23:35:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b3fe587ed2c78d46132bd33e14f42449d410354b

commit b3fe587ed2c78d46132bd33e14f42449d410354b
Author: Alan Modra <amodra@gmail.com>
Date:   Mon Sep 23 08:53:07 2019 +0930

    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.

Diff:
---
 binutils/ChangeLog | 9 +++++++++
 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;



More information about the Binutils-cvs mailing list