binutils stabs type list
authorAlan Modra <amodra@gmail.com>
Tue, 14 Feb 2023 21:21:00 +0000 (07:51 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 15 Feb 2023 02:35:28 +0000 (13:05 +1030)
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.

binutils/stabs.c

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