More fixes for invalid memory accesses triggered by fuzzed binaries.
[deliverable/binutils-gdb.git] / bfd / elf32-avr.c
index 8498d29493e80b7167a59404b42e8e0d306d98d9..adcf1a3c9c77ca896e3d43389d3da084dead822a 100644 (file)
@@ -1,5 +1,5 @@
 /* AVR-specific support for 32-bit ELF
-   Copyright (C) 1999-2014 Free Software Foundation, Inc.
+   Copyright (C) 1999-2015 Free Software Foundation, Inc.
    Contributed by Denis Chertykov <denisc@overta.ru>
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -859,7 +859,11 @@ avr_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_AVR_max);
+  if (r_type >= (unsigned int) R_AVR_max)
+    {
+      _bfd_error_handler (_("%A: invalid AVR reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_avr_howto_table[r_type];
 }
 
@@ -1518,7 +1522,6 @@ bfd_elf_avr_final_write_processing (bfd *abfd,
   elf_elfheader (abfd)->e_machine = EM_AVR;
   elf_elfheader (abfd)->e_flags &= ~ EF_AVR_MACH;
   elf_elfheader (abfd)->e_flags |= val;
-  elf_elfheader (abfd)->e_flags |= EF_AVR_LINKRELAX_PREPARED;
 }
 
 /* Set the right machine number.  */
@@ -1881,10 +1884,22 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
       isymend = isym + symtab_hdr->sh_info;
       for (; isym < isymend; isym++)
        {
-         if (isym->st_shndx == sec_shndx
-             && isym->st_value > addr
-             && isym->st_value <= toaddr)
-           isym->st_value -= count;
+         if (isym->st_shndx == sec_shndx)
+            {
+             if (isym->st_value > addr
+                  && isym->st_value <= toaddr)
+                isym->st_value -= count;
+
+              if (isym->st_value <= addr
+                  && isym->st_value + isym->st_size > addr)
+                {
+                  /* If this assert fires then we have a symbol that ends
+                     part way through an instruction.  Does that make
+                     sense?  */
+                  BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
+                  isym->st_size -= count;
+                }
+            }
        }
     }
 
@@ -1898,11 +1913,22 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
       struct elf_link_hash_entry *sym_hash = *sym_hashes;
       if ((sym_hash->root.type == bfd_link_hash_defined
            || sym_hash->root.type == bfd_link_hash_defweak)
-          && sym_hash->root.u.def.section == sec
-          && sym_hash->root.u.def.value > addr
-          && sym_hash->root.u.def.value <= toaddr)
+          && sym_hash->root.u.def.section == sec)
         {
-          sym_hash->root.u.def.value -= count;
+          if (sym_hash->root.u.def.value > addr
+              && sym_hash->root.u.def.value <= toaddr)
+            sym_hash->root.u.def.value -= count;
+
+          if (sym_hash->root.u.def.value <= addr
+              && (sym_hash->root.u.def.value + sym_hash->size > addr))
+            {
+              /* If this assert fires then we have a symbol that ends
+                 part way through an instruction.  Does that make
+                 sense?  */
+              BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
+                          >= addr + count);
+              sym_hash->size -= count;
+            }
         }
     }
 
This page took 0.025689 seconds and 4 git commands to generate.