binutils stabs type list

Fuzzers have found that specifying a large stab type number results in
lots of memory being requested, as the list is extended with a 16
element array at a time until we reach the given stab type.  It also
takes a long time.  Of course normal sane stab types use small
positive integers, but it's not hard to modify the code to handle type
numbers starting anyhere.

	* stabs.c (struct stab_types): Add base_index.
	(stab_find_slot): Simplify filenum check.  Delete type number
	check.  Don't allocate entire array from 0 to type number,
	allocate a sparse array.
This commit is contained in:
Alan Modra 2023-02-15 07:51:00 +10:30
parent 3cd0b4f2c0
commit 72d225ef9c

View file

@ -121,6 +121,8 @@ struct stab_types
{ {
/* Next set of slots for this file. */ /* Next set of slots for this file. */
struct stab_types *next; struct stab_types *next;
/* Where the TYPES array starts. */
unsigned int base_index;
/* Types indexed by type number. */ /* Types indexed by type number. */
#define STAB_TYPES_SLOTS (16) #define STAB_TYPES_SLOTS (16)
debug_type types[STAB_TYPES_SLOTS]; debug_type types[STAB_TYPES_SLOTS];
@ -3413,40 +3415,32 @@ stab_emit_pending_vars (void *dhandle, struct stab_handle *info)
static debug_type * static debug_type *
stab_find_slot (struct stab_handle *info, const int *typenums) stab_find_slot (struct stab_handle *info, const int *typenums)
{ {
int filenum; unsigned int filenum;
int tindex; unsigned int tindex;
unsigned int base_index;
struct stab_types **ps; struct stab_types **ps;
filenum = typenums[0]; filenum = typenums[0];
tindex = typenums[1]; tindex = typenums[1];
if (filenum < 0 || (unsigned int) filenum >= info->files) if (filenum >= info->files)
{ {
fprintf (stderr, _("Type file number %d out of range\n"), filenum); fprintf (stderr, _("Type file number %d out of range\n"), filenum);
return NULL; return NULL;
} }
if (tindex < 0)
{
fprintf (stderr, _("Type index number %d out of range\n"), tindex);
return NULL;
}
ps = info->file_types + filenum; ps = info->file_types + filenum;
base_index = tindex / STAB_TYPES_SLOTS * STAB_TYPES_SLOTS;
tindex -= base_index;
while (*ps && (*ps)->base_index < base_index)
ps = &(*ps)->next;
while (tindex >= STAB_TYPES_SLOTS) if (*ps == NULL || (*ps)->base_index != base_index)
{ {
if (*ps == NULL) struct stab_types *n = xcalloc (1, sizeof (*n));
{ n->next = *ps;
*ps = (struct stab_types *) xmalloc (sizeof **ps); n->base_index = base_index;
memset (*ps, 0, sizeof **ps); *ps = n;
}
ps = &(*ps)->next;
tindex -= STAB_TYPES_SLOTS;
}
if (*ps == NULL)
{
*ps = (struct stab_types *) xmalloc (sizeof **ps);
memset (*ps, 0, sizeof **ps);
} }
return (*ps)->types + tindex; return (*ps)->types + tindex;