PR28173, nds32_elf_howto_table index out of bounds

Message ID YQ06LzX/JLLRKKdL@squeak.grove.modra.org
State New
Headers show
Series
  • PR28173, nds32_elf_howto_table index out of bounds
Related show

Commit Message

Alan Modra via Binutils Aug. 6, 2021, 1:33 p.m.
Indexing the howto table was seriously broken by a missing entry, and
use of assertions about user input rather than testing the input.

	* elf32-nds32.c (nds32_elf_howto_table): Add missing empty howto.
	(bfd_elf32_bfd_reloc_type_table_lookup): Replace assertions with
	range checks.  Return NULL if unsupported reloc type.  Remove
	dead code.  Take an unsigned int param.
	(nds32_info_to_howto_rel): Test for NULL howto or howto name
	return from lookup.  Remove assertion.
	(nds32_info_to_howto): Remove unnecessary ATTRIBUTE_UNUSED.
	Test for NULL howto or howto name return from lookup.


-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c
index 5eb029524df..0aa7c9ee564 100644
--- a/bfd/elf32-nds32.c
+++ b/bfd/elf32-nds32.c
@@ -1954,6 +1954,8 @@  static reloc_howto_type nds32_elf_howto_table[] =
 	 0xffffffff,		/* dst_mask  */
 	 false),		/* pcrel_offset  */
 
+  EMPTY_HOWTO (114),
+
   HOWTO2 (R_NDS32_TLS_IE_LO12,	/* type  */
 	 0,			/* rightshift  */
 	 2,			/* size (0 = byte, 1 = short, 2 = long)  */
@@ -3184,26 +3186,19 @@  bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 }
 
 static reloc_howto_type *
-bfd_elf32_bfd_reloc_type_table_lookup (enum elf_nds32_reloc_type code)
+bfd_elf32_bfd_reloc_type_table_lookup (unsigned int code)
 {
   if (code < R_NDS32_RELAX_ENTRY)
     {
-      BFD_ASSERT (code < ARRAY_SIZE (nds32_elf_howto_table));
-      return &nds32_elf_howto_table[code];
+      if (code < ARRAY_SIZE (nds32_elf_howto_table))
+	return &nds32_elf_howto_table[code];
     }
   else
     {
-      if ((size_t) (code - R_NDS32_RELAX_ENTRY)
-	  >= ARRAY_SIZE (nds32_elf_relax_howto_table))
-	{
-	  int i = code;
-	  i += 1;
-	}
-
-      BFD_ASSERT ((size_t) (code - R_NDS32_RELAX_ENTRY)
-		  < ARRAY_SIZE (nds32_elf_relax_howto_table));
-      return &nds32_elf_relax_howto_table[code - R_NDS32_RELAX_ENTRY];
+      if (code - R_NDS32_RELAX_ENTRY < ARRAY_SIZE (nds32_elf_relax_howto_table))
+	return &nds32_elf_relax_howto_table[code - R_NDS32_RELAX_ENTRY];
     }
+  return NULL;
 }
 
 static reloc_howto_type *
@@ -3228,10 +3223,12 @@  static bool
 nds32_info_to_howto_rel (bfd *abfd, arelent *cache_ptr,
 			 Elf_Internal_Rela *dst)
 {
-  enum elf_nds32_reloc_type r_type;
+  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
 
-  r_type = ELF32_R_TYPE (dst->r_info);
-  if (r_type > R_NDS32_GNU_VTENTRY)
+  cache_ptr->howto = NULL;
+  if (r_type <= R_NDS32_GNU_VTENTRY)
+    cache_ptr->howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type);
+  if (cache_ptr->howto == NULL || cache_ptr->howto->name == NULL)
     {
       /* xgettext:c-format */
       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
@@ -3239,30 +3236,28 @@  nds32_info_to_howto_rel (bfd *abfd, arelent *cache_ptr,
       bfd_set_error (bfd_error_bad_value);
       return false;
     }
-
-  BFD_ASSERT (ELF32_R_TYPE (dst->r_info) <= R_NDS32_GNU_VTENTRY);
-  cache_ptr->howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type);
   return true;
 }
 
 static bool
-nds32_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
+nds32_info_to_howto (bfd *abfd, arelent *cache_ptr,
 		     Elf_Internal_Rela *dst)
 {
   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
 
-  if ((r_type == R_NDS32_NONE)
-      || ((r_type > R_NDS32_GNU_VTENTRY)
-	  && (r_type < R_NDS32_max)))
+  cache_ptr->howto = NULL;
+  if (r_type == R_NDS32_NONE
+      || r_type > R_NDS32_GNU_VTENTRY)
+    cache_ptr->howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type);
+  if (cache_ptr->howto == NULL || cache_ptr->howto->name == NULL)
     {
-      cache_ptr->howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type);
-      return true;
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+			  abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
     }
-
-  /* xgettext:c-format */
-  _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type);
-  bfd_set_error (bfd_error_bad_value);
-  return false;
+  return true;
 }
 
 /* Support for core dump NOTE sections.