Fix illegal memory access problems with readelf processing corrupt RL78 binaries.
authorNick Clifton <nickc@redhat.com>
Tue, 14 Feb 2017 13:24:09 +0000 (13:24 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 14 Feb 2017 13:24:09 +0000 (13:24 +0000)
PR binutils/21155
* readelf.c (IN_RANGE): New macro.  Tests for an address + offset
being within a given range.
(target_specific_reloc_handling): Use macro to test for underflow
as well as overflow of reloc offset.

binutils/ChangeLog
binutils/readelf.c

index 5baf48efa21f92854972d5238271e6b07c231567..5d60a78a159b34a4a8c1a857e91cd7a9d63c0c3a 100644 (file)
@@ -1,3 +1,11 @@
+2017-02-14  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/21155
+       * readelf.c (IN_RANGE): New macro.  Tests for an address + offset
+       being within a given range.
+       (target_specific_reloc_handling): Use macro to test for underflow
+       as well as overflow of reloc offset.
+
 2017-02-13  Nick Clifton  <nickc@redhat.com>
 
        PR binutils/21150
index c73a3275ea3a087a671f7d771cab990cde1a3640..c4bddcdb711db673a3a15aeb52fd1aacb867c61f 100644 (file)
@@ -11596,6 +11596,9 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED)
   return 1;
 }
 
+#define IN_RANGE(START,END,ADDR,OFF)           \
+  (((ADDR) >= (START)) && ((ADDR) + (OFF) < (END)))
+
 /* Check to see if the given reloc needs to be handled in a target specific
    manner.  If so then process the reloc and return TRUE otherwise return
    FALSE.
@@ -11678,12 +11681,12 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
                    value = reloc->r_addend + (symtab[sym_index].st_value
                                               - saved_sym->st_value);
 
-                   if (start + reloc->r_offset + reloc_size >= end)
-                     /* PR 21137 */
-                     error (_("MSP430 sym diff reloc writes past end of section (%p vs %p)\n"),
-                            start + reloc->r_offset + reloc_size, end);
-                   else
+                   if (IN_RANGE (start, end, start + reloc->r_offset, reloc_size))
                      byte_put (start + reloc->r_offset, value, reloc_size);
+                   else
+                     /* PR 21137 */
+                     error (_("MSP430 sym diff reloc contains invalid offset: 0x%lx\n"),
+                            (long) reloc->r_offset);
                  }
 
                saved_sym = NULL;
@@ -11737,11 +11740,11 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
                    value = reloc->r_addend + (symtab[sym_index].st_value
                                               - saved_sym->st_value);
 
-                   if (start + reloc->r_offset + reloc_size >= end)
-                     error (_("MN10300 sym diff reloc writes past end of section (%p vs %p)\n"),
-                            start + reloc->r_offset + reloc_size, end);
-                   else
+                   if (IN_RANGE (start, end, start + reloc->r_offset, reloc_size))
                      byte_put (start + reloc->r_offset, value, reloc_size);
+                   else
+                     error (_("MN10300 sym diff reloc contains invalid offset: 0x%lx\n"),
+                            (long) reloc->r_offset);
                  }
 
                saved_sym = NULL;
@@ -11789,20 +11792,20 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
            break;
 
          case 0x41: /* R_RL78_ABS32.  */
-           if (start + reloc->r_offset + 4 >= end)
-             error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"),
-                    start + reloc->r_offset + 2, end);
-           else
+           if (IN_RANGE (start, end, start + reloc->r_offset, 4))
              byte_put (start + reloc->r_offset, value, 4);
+           else
+             error (_("RL78 sym diff reloc contains invalid offset: 0x%lx\n"),
+                    (long) reloc->r_offset);
            value = 0;
            return TRUE;
 
          case 0x43: /* R_RL78_ABS16.  */
-           if (start + reloc->r_offset + 2 >= end)
-             error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"),
-                    start + reloc->r_offset + 2, end);
-           else
+           if (IN_RANGE (start, end, start + reloc->r_offset, 2))
              byte_put (start + reloc->r_offset, value, 2);
+           else
+             error (_("RL78 sym diff reloc contains invalid offset: 0x%lx\n"),
+                    (long) reloc->r_offset);
            value = 0;
            return TRUE;