From 7a089e0302382f4d4e077941156e1eaa68d01393 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Mon, 6 Apr 2026 22:58:22 +0930
Subject: [PATCH] PR 34049 buffer overflow in xcoff_link_add_symbols

The fact that coffcode.h:coff_set_alignment_hook for rs6000 removes
sections can result in target_index > section_count.  Thus any array
indexed by target_index must not be sized by section_count.

	PR ld/34049
	* xcofflink.c (xcoff_link_add_symbols): Size reloc_info array
	using max target_index.

CVE: CVE-2026-6846
Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=7a089e0302382f4d4e077941156e1eaa68d01393]

Signed-off-by: Alan Modra <amodra@gmail.com>
(cherry picked from commit 7a089e0302382f4d4e077941156e1eaa68d01393)
Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
---
 bfd/xcofflink.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index 1781182fa6a..7f1c0df760f 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -1335,6 +1335,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
   } *reloc_info = NULL;
   bfd_size_type amt;
   unsigned short visibility;
+  unsigned int max_target_index;
 
   keep_syms = obj_coff_keep_syms (abfd);
 
@@ -1398,7 +1399,19 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
      order by VMA within a given section, so we handle this by
      scanning along the relocs as we process the csects.  We index
      into reloc_info using the section target_index.  */
-  amt = abfd->section_count + 1;
+  max_target_index = 0;
+  for (o = abfd->section_last; o != NULL; o = o->prev)
+    if (o->target_index != 0)
+      {
+	/* The last section added from the object file will have the
+	   highest target_index.  See coffgen.c coff_real_object_p and
+	   make_a_section_from_file.  Sections added by
+	   xcoff_link_create_extra_sections will have a zero
+	   target_index.  */
+	max_target_index = o->target_index;
+	break;
+      }
+  amt = max_target_index + 1;
   amt *= sizeof (struct reloc_info_struct);
   reloc_info = bfd_zmalloc (amt);
   if (reloc_info == NULL)
-- 
2.43.7

