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
>