From b32e566ba6ee02687c6def22ade0899076adf7dd Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 14 Feb 2017 13:24:09 +0000 Subject: [PATCH] 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. --- binutils/ChangeLog | 8 ++++++++ binutils/readelf.c | 37 ++++++++++++++++++++----------------- 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 + + 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 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; -- 2.30.2