PR28173, nds32_elf_howto_table index out of bounds
authorAlan Modra <amodra@gmail.com>
Fri, 6 Aug 2021 09:05:23 +0000 (18:35 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 6 Aug 2021 13:36:40 +0000 (23:06 +0930)
Indexing the howto table was seriously broken by a missing entry, and
use of assertions about user input rather than testing the input.

PR 28173
* 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.

bfd/elf32-nds32.c

index 5eb029524df201af777c28a3732b0161168b5f8b..0aa7c9ee564c9201ca5574404211c84df36d9350 100644 (file)
@@ -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.