[binutils-gdb] PR 33223 ppc64: segfault on unknown relocation

Alan Modra amodra@sourceware.org
Tue Jul 29 13:11:34 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8fd6a9c70b4b67541dbafba64d0e215eada05ff1

commit 8fd6a9c70b4b67541dbafba64d0e215eada05ff1
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Jul 29 10:39:51 2025 +0930

    PR 33223 ppc64: segfault on unknown relocation
    
    Bounds check accesses to ppc64_elf_howto_table and don't dereference a
    NULL howto.  I think this catches all cases where that might happen.
    
            PR 33223
    bfd/
            * elf64-ppc.c (ppc64_elf_info_to_howto): Consolidate error handling.
            (ppc64_elf_check_relocs): Tidy error messages.
            (ppc64_elf_relocate_section): Don't segfault when attempting to
            report an unsupported relocation.  Don't pass a NULL howto to
            _bfd_clear_contents.
    ld/
            * testsuite/ld-powerpc/elfv2-2so.d: Adjust to suit error message
            change.

Diff:
---
 bfd/elf64-ppc.c                     | 40 +++++++++++++++++++------------------
 ld/testsuite/ld-powerpc/elfv2-2so.d |  2 +-
 2 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index e6c90a68b82..78680630c6e 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -1379,7 +1379,8 @@ ppc64_elf_info_to_howto (bfd *abfd, arelent *cache_ptr,
     ppc_howto_init ();
 
   type = ELF64_R_TYPE (dst->r_info);
-  if (type >= ARRAY_SIZE (ppc64_elf_howto_table))
+  if (type >= ARRAY_SIZE (ppc64_elf_howto_table)
+      || ppc64_elf_howto_table[type] == NULL)
     {
       /* xgettext:c-format */
       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
@@ -1388,15 +1389,6 @@ ppc64_elf_info_to_howto (bfd *abfd, arelent *cache_ptr,
       return false;
     }
   cache_ptr->howto = ppc64_elf_howto_table[type];
-  if (cache_ptr->howto == NULL || cache_ptr->howto->name == NULL)
-    {
-      /* xgettext:c-format */
-      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
-			  abfd, type);
-      bfd_set_error (bfd_error_bad_value);
-      return false;
-    }
-
   return true;
 }
 
@@ -5104,7 +5096,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	      if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
 		ppc_howto_init ();
 	      /* xgettext:c-format */
-	      info->callbacks->einfo (_("%H: %s reloc unsupported "
+	      info->callbacks->einfo (_("%H: %s unsupported "
 					"in shared libraries and PIEs\n"),
 				      abfd, sec, rel->r_offset,
 				      ppc64_elf_howto_table[r_type]->name);
@@ -5274,7 +5266,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  if (ppc64_sec->sec_type != sec_toc
 	      || rel->r_offset % 8 != 0)
 	    {
-	      info->callbacks->einfo (_("%H: %s reloc unsupported here\n"),
+	      info->callbacks->einfo (_("%H: %s unsupported here\n"),
 				      abfd, sec, rel->r_offset,
 				      ppc64_elf_howto_table[r_type]->name);
 	      bfd_set_error (bfd_error_bad_value);
@@ -15685,9 +15677,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
       if (sec != NULL && discarded_section (sec))
 	{
-	  _bfd_clear_contents (ppc64_elf_howto_table[r_type],
-			       input_bfd, input_section,
-			       contents, rel->r_offset);
+	  if (r_type < ARRAY_SIZE (ppc64_elf_howto_table)
+	      && ppc64_elf_howto_table[r_type] != NULL)
+	    _bfd_clear_contents (ppc64_elf_howto_table[r_type],
+				 input_bfd, input_section,
+				 contents, rel->r_offset);
 	  wrel->r_offset = rel->r_offset;
 	  wrel->r_info = 0;
 	  wrel->r_addend = 0;
@@ -15750,6 +15744,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	 relocs are used with non-tls syms.  */
       if (r_symndx != STN_UNDEF
 	  && r_type != R_PPC64_NONE
+	  && r_type < ARRAY_SIZE (ppc64_elf_howto_table)
+	  && ppc64_elf_howto_table[r_type] != NULL
 	  && (h == NULL
 	      || h->elf.root.type == bfd_link_hash_defined
 	      || h->elf.root.type == bfd_link_hash_defweak)
@@ -16865,9 +16861,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       switch (r_type)
 	{
 	default:
-	  /* xgettext:c-format */
-	  _bfd_error_handler (_("%pB: %s unsupported"),
-			      input_bfd, ppc64_elf_howto_table[r_type]->name);
+	  if (r_type < ARRAY_SIZE (ppc64_elf_howto_table)
+	      && ppc64_elf_howto_table[r_type] != NULL)
+	    /* xgettext:c-format */
+	    _bfd_error_handler (_("%pB: %s unsupported"),
+				input_bfd, ppc64_elf_howto_table[r_type]->name);
+	  else
+	    /* xgettext:c-format */
+	    _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+				input_bfd, r_type);
 
 	  bfd_set_error (bfd_error_bad_value);
 	  ret = false;
@@ -17909,7 +17911,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
 	 because such sections are not SEC_ALLOC and thus ld.so will
 	 not process them.  */
-      howto = ppc64_elf_howto_table[(int) r_type];
+      howto = ppc64_elf_howto_table[r_type];
       if (unresolved_reloc
 	  && !((input_section->flags & SEC_DEBUGGING) != 0
 	       && h->elf.def_dynamic)
diff --git a/ld/testsuite/ld-powerpc/elfv2-2so.d b/ld/testsuite/ld-powerpc/elfv2-2so.d
index 56b143428fd..18bc87f09ac 100644
--- a/ld/testsuite/ld-powerpc/elfv2-2so.d
+++ b/ld/testsuite/ld-powerpc/elfv2-2so.d
@@ -2,4 +2,4 @@
 #source: elfv2-2b.s
 #as: -a64
 #ld: -melf64ppc -shared -e f1
-#error: .* R_PPC64_ADDR64_LOCAL reloc unsupported in shared libraries and PIEs.*
+#error: .* R_PPC64_ADDR64_LOCAL unsupported in shared libraries and PIEs.*


More information about the Binutils-cvs mailing list