From 8fd6a9c70b4b67541dbafba64d0e215eada05ff1 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 29 Jul 2025 10:39:51 +0930 Subject: [PATCH] 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. --- 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.* -- 2.47.2