]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
m32r hi/lo reloc offset sanity checks
authorAlan Modra <amodra@gmail.com>
Mon, 20 Apr 2026 06:11:14 +0000 (15:41 +0930)
committerAlan Modra <amodra@gmail.com>
Mon, 20 Apr 2026 06:11:14 +0000 (15:41 +0930)
This fixes another fuzzer attack.

* elf32-m32r.c (m32r_elf_hi16_reloc): Properly check reloc offset.
(m32r_elf_relocate_hi16): Add input_section param.  Return status.
Sanity check reloc offsets before accessing section contents.
Simplify sign extension.
(m32r_elf_lo16_reloc): Sanity check reloc offset.  Simplify
sign extension.  Remove unnecessary casts.
(m32r_elf_relocate_section): Adjust m32r_elf_relocate_hi16 calls.

bfd/elf32-m32r.c

index c10195b154d00deec2374b7cf7f7f096a1e5bd91..68ef7122368ae12a24eb0c2a6311984c5c3cda30 100644 (file)
@@ -353,7 +353,7 @@ m32r_elf_free_cached_info (bfd *abfd)
 
 
 static bfd_reloc_status_type
-m32r_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+m32r_elf_hi16_reloc (bfd *abfd,
                     arelent *reloc_entry,
                     asymbol *symbol,
                     void * data,
@@ -378,7 +378,8 @@ m32r_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
     }
 
   /* Sanity check the address (offset in section).  */
-  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, input_section,
+                                 reloc_entry->address))
     return bfd_reloc_outofrange;
 
   ret = bfd_reloc_ok;
@@ -413,8 +414,9 @@ m32r_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 
 /* Handle an M32R ELF HI16 reloc.  */
 
-static void
+static bfd_reloc_status_type
 m32r_elf_relocate_hi16 (bfd *input_bfd,
+                       asection *input_section,
                        int type,
                        Elf_Internal_Rela *relhi,
                        Elf_Internal_Rela *rello,
@@ -423,6 +425,11 @@ m32r_elf_relocate_hi16 (bfd *input_bfd,
 {
   unsigned long insn;
   bfd_vma addlo;
+  bfd_vma end = bfd_get_section_limit_octets (input_bfd, input_section);
+
+  if (relhi->r_offset > end || end - relhi->r_offset < 4
+      || rello->r_offset > end || end - rello->r_offset < 4)
+    return bfd_reloc_outofrange;
 
   insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
 
@@ -435,13 +442,13 @@ m32r_elf_relocate_hi16 (bfd *input_bfd,
   addend += ((insn & 0xffff) << 16) + addlo;
 
   /* Reaccount for sign extension of low part.  */
-  if (type == R_M32R_HI16_SLO
-      && (addend & 0x8000) != 0)
-    addend += 0x10000;
+  if (type == R_M32R_HI16_SLO)
+    addend += 0x8000;
 
   bfd_put_32 (input_bfd,
              (insn & 0xffff0000) | ((addend >> 16) & 0xffff),
              contents + relhi->r_offset);
+  return bfd_reloc_ok;
 }
 
 /* Do an R_M32R_LO16 relocation.  This is a straightforward 16 bit
@@ -470,6 +477,10 @@ m32r_elf_lo16_reloc (bfd *input_bfd,
       return bfd_reloc_ok;
     }
 
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, input_bfd, input_section,
+                                 reloc_entry->address))
+    return bfd_reloc_outofrange;
+
   sdata = m32r_elf_section_data (input_section);
   if (sdata->m32r_hi16_list != NULL)
     {
@@ -488,16 +499,15 @@ m32r_elf_lo16_reloc (bfd *input_bfd,
             find the low 16 bits of the addend needed by the LO16.  */
          insn = bfd_get_32 (input_bfd, l->addr);
          vallo = ((bfd_get_32 (input_bfd, (bfd_byte *) data + reloc_entry->address)
-                  & 0xffff) ^ 0x8000) - 0x8000;
+                   & 0xffff) ^ 0x8000) - 0x8000;
          val = ((insn & 0xffff) << 16) + vallo;
          val += l->addend;
 
          /* Reaccount for sign extension of low part.  */
-         if ((val & 0x8000) != 0)
-           val += 0x10000;
+         val += 0x8000;
 
-         insn = (insn &~ (bfd_vma) 0xffff) | ((val >> 16) & 0xffff);
-         bfd_put_32 (input_bfd, (bfd_vma) insn, l->addr);
+         insn = (insn & ~0xffff) | ((val >> 16) & 0xffff);
+         bfd_put_32 (input_bfd, insn, l->addr);
 
          next = l->next;
          free (l);
@@ -2451,11 +2461,9 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
                continue;
              if (lorel < relend
                  && ELF32_R_TYPE (lorel->r_info) == R_M32R_LO16)
-               {
-                 m32r_elf_relocate_hi16 (input_bfd, r_type, rel, lorel,
-                                         contents, addend);
-                 r = bfd_reloc_ok;
-               }
+               r = m32r_elf_relocate_hi16 (input_bfd, input_section,
+                                           r_type, rel, lorel,
+                                           contents, addend);
              else
                r = _bfd_relocate_contents (howto, input_bfd,
                                            addend, contents + offset);
@@ -2778,11 +2786,9 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
                  continue;
                if (lorel < relend
                    && ELF32_R_TYPE (lorel->r_info) == R_M32R_LO16)
-                 {
-                   m32r_elf_relocate_hi16 (input_bfd, r_type, rel, lorel,
-                                           contents, relocation + addend);
-                   r = bfd_reloc_ok;
-                 }
+                 r = m32r_elf_relocate_hi16 (input_bfd, input_section,
+                                             r_type, rel, lorel,
+                                             contents, relocation + addend);
                else
                  r = _bfd_final_link_relocate (howto, input_bfd, input_section,
                                                contents, offset,