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 */
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.