summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2017-02-14 13:24:09 +0000
committerNick Clifton <nickc@redhat.com>2017-02-14 13:24:09 +0000
commitb32e566ba6ee02687c6def22ade0899076adf7dd (patch)
tree1523a3aea8acafb835455833fa07e867aaf4e091
parent7e0de605cbacbbbb2531bb70506c0843aea13111 (diff)
downloadbinutils-gdb-b32e566ba6ee02687c6def22ade0899076adf7dd.tar.gz
Fix illegal memory access problems with readelf processing corrupt RL78 binaries.
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.
-rw-r--r--binutils/ChangeLog8
-rw-r--r--binutils/readelf.c37
2 files changed, 28 insertions, 17 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 5baf48efa21..5d60a78a159 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -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
diff --git a/binutils/readelf.c b/binutils/readelf.c
index c73a3275ea3..c4bddcdb711 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -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;