obj_coff_sym_hashes sanity checks

Message ID acpXoX4TTPSInPRi@squeak.grove.modra.org
State New
Headers
Series obj_coff_sym_hashes sanity checks |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply

Commit Message

Alan Modra March 30, 2026, 10:59 a.m. UTC
  Various places in cofflink.c and coffgen.c assume the r_symndx
indexing sym_hashes is sane.  Add some checks.

	* cofflink.c (_bfd_coff_link_input_bfd): Sanity check r_symndx
	against obj_raw_syment_count before using it to index sym_hashes,
	rather than just checking for the special -1 value.
	(_bfd_coff_generic_relocate_section): Delete unnecessary check.
	Sanity check weak symndx2 against obj_raw_syment_count.
	* coffgen.c (_bfd_coff_gc_mark_hook): Sanity check weak symndx2
	against obj_raw_syment_count.
	(_bfd_coff_gc_mark_rsec): Sanity check r_symndx.
  

Patch

diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index 030dbc1dc79..97685a61087 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -2953,9 +2953,10 @@  _bfd_coff_gc_mark_hook (asection *sec,
 	      /* PE weak externals.  A weak symbol may include an auxiliary
 		 record indicating that if the weak symbol is not resolved,
 		 another external symbol is used instead.  */
-	      struct coff_link_hash_entry *h2 =
-		h->auxbfd->tdata.coff_obj_data->sym_hashes
-		[h->aux->x_sym.x_tagndx.u32];
+	      struct coff_link_hash_entry *h2 = NULL;
+	      unsigned long symndx2 = h->aux->x_sym.x_tagndx.u32;
+	      if (symndx2 < obj_raw_syment_count (h->auxbfd))
+		h2 = obj_coff_sym_hashes (h->auxbfd)[symndx2];
 
 	      if (h2 && h2->root.type != bfd_link_hash_undefined)
 		return  h2->root.u.def.section;
@@ -2982,8 +2983,11 @@  _bfd_coff_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 			struct coff_reloc_cookie *cookie)
 {
   struct coff_link_hash_entry *h;
+  unsigned long rsym = cookie->rel->r_symndx;
 
-  h = cookie->sym_hashes[cookie->rel->r_symndx];
+  if (rsym >= obj_raw_syment_count (cookie->abfd))
+    return NULL;
+  h = cookie->sym_hashes[rsym];
   if (h != NULL)
     {
       while (h->root.type == bfd_link_hash_indirect
@@ -2995,7 +2999,7 @@  _bfd_coff_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 
   return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
 			  &(cookie->symbols
-			    + obj_convert (sec->owner)[cookie->rel->r_symndx])->native->u.syment);
+			    + obj_convert (sec->owner)[rsym])->native->u.syment);
 }
 
 static bool _bfd_coff_gc_mark
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 02b68814ab4..3504b2d4a0c 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -2409,8 +2409,8 @@  _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
 	    {
 	      struct coff_link_hash_entry *h;
 	      asection *ps = NULL;
-	      long symndx = irel->r_symndx;
-	      if (symndx < 0)
+	      unsigned long symndx = irel->r_symndx;
+	      if (symndx >= obj_raw_syment_count (input_bfd))
 		continue;
 	      h = obj_coff_sym_hashes (input_bfd)[symndx];
 	      if (h == NULL)
@@ -2463,7 +2463,8 @@  _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
 		  /* Adjust the reloc address and symbol index.  */
 		  irel->r_vaddr += offset;
 
-		  if (irel->r_symndx == -1)
+		  if ((unsigned long) irel->r_symndx
+		      >= obj_raw_syment_count (input_bfd))
 		    continue;
 
 		  if (adjust_symndx)
@@ -2971,8 +2972,7 @@  _bfd_coff_generic_relocate_section (bfd *output_bfd,
 	  h = NULL;
 	  sym = NULL;
 	}
-      else if (symndx < 0
-	       || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
+      else if ((unsigned long) symndx >= obj_raw_syment_count (input_bfd))
 	{
 	  _bfd_error_handler
 	    /* xgettext: c-format */
@@ -3065,9 +3065,10 @@  _bfd_coff_generic_relocate_section (bfd *output_bfd,
 		     will resolve a weak external only if a normal
 		     external causes the library member to be linked.
 		     See also linker.c: generic_link_check_archive_element. */
-		  struct coff_link_hash_entry *h2 =
-		    h->auxbfd->tdata.coff_obj_data->sym_hashes
-		    [h->aux->x_sym.x_tagndx.u32];
+		  struct coff_link_hash_entry *h2 = NULL;
+		  unsigned long symndx2 = h->aux->x_sym.x_tagndx.u32;
+		  if (symndx2 < obj_raw_syment_count (h->auxbfd))
+		    h2 = obj_coff_sym_hashes (h->auxbfd)[symndx2];
 
 		  if (!h2 || h2->root.type == bfd_link_hash_undefined)
 		    {