Hi mustafa,

On Tue, Nov 3, 2026 at 3:27 AM mustafa <[email protected]> wrote:
>
> print_debug_macinfo_section and print_debug_macro_section called alloca
> for each CU that has a macro attribute, and print_debug_macinfo_section
> also allocated an array with one entry per CU. The number of CUs is
> bounded only by the size of the input file, so a large .debug_info
> exhausts the stack.
>
> Use xmalloc. The macinfo list is freed as it is copied into the array,
> the array and the macro list are freed through cleanup attributes. Move
> free_ptr to the top of the file so these functions can use it.
>
> Signed-off-by: mohammed mustafa <[email protected]>
> ---
>  src/readelf.c | 36 ++++++++++++++++++++++++------------
>  1 file changed, 24 insertions(+), 12 deletions(-)
>
> diff --git a/src/readelf.c b/src/readelf.c
> index 12118b4f..21db75ce 100644
> --- a/src/readelf.c
> +++ b/src/readelf.c
> @@ -168,6 +168,12 @@ static struct argp argp =
>    options, parse_opt, args_doc, doc, NULL, NULL, NULL
>  };
>
> +static void
> +free_ptr (void *p)
> +{
> +  free (*(void **) p);
> +}

Please avoid the cleanup attribute as mentioned in a previous review.

> +
>  /* If non-null, the section from which we should read to (compressed) ELF.  
> */
>  static const char *elf_input_section = NULL;
>
> @@ -10068,6 +10074,16 @@ struct mac_culist
>    struct mac_culist *next;
>  };
>
> +static void
> +free_mac_culist (struct mac_culist **culist)
> +{
> +  while (*culist != NULL)
> +    {
> +      struct mac_culist *next = (*culist)->next;
> +      free (*culist);
> +      *culist = next;
> +    }
> +}
>
>  static int
>  mac_compare (const void *p1, const void *p2)
> @@ -10122,7 +10138,7 @@ print_debug_macinfo_section (Dwfl_Module
> *dwflmod __attribute__ ((unused)),
>        if (dwarf_formudata (&attr, &macoff) != 0)
>         continue;
>
> -      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof 
> (*newp));
> +      struct mac_culist *newp = xmalloc (sizeof (*newp));
>        newp->die = cudie;
>        newp->offset = macoff;
>        newp->files = NULL;
> @@ -10132,8 +10148,8 @@ print_debug_macinfo_section (Dwfl_Module
> *dwflmod __attribute__ ((unused)),
>      }
>
>    /* Convert the list into an array for easier consumption.  */
> -  struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
> -                                                        * sizeof (*cus));
> +  struct mac_culist *cus __attribute__ ((cleanup (free_ptr)))
> +    = xmalloc ((nculist + 1) * sizeof (*cus));

print_debug_macinfo_section increments the cus pointer.  When free_ptr
is called cus may not point to the address that this xmalloc returned,
causing an invalid free.

Aaron

>    /* Add sentinel.  */
>    cus[nculist].offset = data->d_size;
>    cus[nculist].files = (Dwarf_Files *) -1l;
> @@ -10142,8 +10158,10 @@ print_debug_macinfo_section (Dwfl_Module
> *dwflmod __attribute__ ((unused)),
>        for (size_t cnt = nculist - 1; culist != NULL; --cnt)
>         {
>           assert (cnt < nculist);
> +         struct mac_culist *next = culist->next;
>           cus[cnt] = *culist;
> -         culist = culist->next;
> +         free (culist);
> +         culist = next;
>         }
>
>        /* Sort the array according to the offset in the .debug_macinfo
> @@ -10267,7 +10285,7 @@ print_debug_macro_section (Dwfl_Module
> *dwflmod __attribute__ ((unused)),
>    Dwarf_Off offset;
>    Dwarf_Off ncu = 0;
>    size_t hsize;
> -  struct mac_culist *culist = NULL;
> +  struct mac_culist *culist __attribute__ ((cleanup (free_mac_culist))) = 
> NULL;
>    while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 
> 0)
>      {
>        Dwarf_Die cudie;
> @@ -10282,7 +10300,7 @@ print_debug_macro_section (Dwfl_Module
> *dwflmod __attribute__ ((unused)),
>        if (dwarf_formudata (&attr, &lineoff) != 0)
>         continue;
>
> -      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof 
> (*newp));
> +      struct mac_culist *newp = xmalloc (sizeof (*newp));
>        newp->die = cudie;
>        newp->offset = lineoff;
>        newp->files = NULL;
> @@ -11860,12 +11878,6 @@ convert (Elf *core, Elf_Type type, uint_fast16_t 
> count,
>
>  typedef uint8_t GElf_Byte;
>
> -static void
> -free_ptr (void *p)
> -{
> -  free (*(void **) p);
> -}
> -
>  static unsigned int
>  handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
>                   unsigned int colno, size_t *repeated_size)
> --
> 2.53.0
>

Reply via email to