PR28173, nds32_elf_howto_table index out of bounds

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.
This commit is contained in:
Alan Modra
2021-08-06 18:35:23 +09:30
parent 352bd3aa1c
commit a379e7588c

View File

@ -1954,6 +1954,8 @@ static reloc_howto_type nds32_elf_howto_table[] =
0xffffffff, /* dst_mask */ 0xffffffff, /* dst_mask */
false), /* pcrel_offset */ false), /* pcrel_offset */
EMPTY_HOWTO (114),
HOWTO2 (R_NDS32_TLS_IE_LO12, /* type */ HOWTO2 (R_NDS32_TLS_IE_LO12, /* type */
0, /* rightshift */ 0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */ 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 * 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) if (code < R_NDS32_RELAX_ENTRY)
{ {
BFD_ASSERT (code < ARRAY_SIZE (nds32_elf_howto_table)); if (code < ARRAY_SIZE (nds32_elf_howto_table))
return &nds32_elf_howto_table[code]; return &nds32_elf_howto_table[code];
} }
else else
{ {
if ((size_t) (code - R_NDS32_RELAX_ENTRY) if (code - R_NDS32_RELAX_ENTRY < ARRAY_SIZE (nds32_elf_relax_howto_table))
>= ARRAY_SIZE (nds32_elf_relax_howto_table)) return &nds32_elf_relax_howto_table[code - R_NDS32_RELAX_ENTRY];
{
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];
} }
return NULL;
} }
static reloc_howto_type * static reloc_howto_type *
@ -3228,10 +3223,12 @@ static bool
nds32_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, nds32_info_to_howto_rel (bfd *abfd, arelent *cache_ptr,
Elf_Internal_Rela *dst) 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); cache_ptr->howto = NULL;
if (r_type > R_NDS32_GNU_VTENTRY) 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 */ /* xgettext:c-format */
_bfd_error_handler (_("%pB: unsupported relocation type %#x"), _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); bfd_set_error (bfd_error_bad_value);
return false; 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; return true;
} }
static bool 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) Elf_Internal_Rela *dst)
{ {
unsigned int r_type = ELF32_R_TYPE (dst->r_info); unsigned int r_type = ELF32_R_TYPE (dst->r_info);
if ((r_type == R_NDS32_NONE) cache_ptr->howto = NULL;
|| ((r_type > R_NDS32_GNU_VTENTRY) if (r_type == R_NDS32_NONE
&& (r_type < R_NDS32_max))) || 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); /* xgettext:c-format */
return true; _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
abfd, r_type);
bfd_set_error (bfd_error_bad_value);
return false;
} }
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;
} }
/* Support for core dump NOTE sections. /* Support for core dump NOTE sections.