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 is freed through its base pointer, because the array pointer is advanced while parsing. The macro list is freed by free_mac_culist. Both functions free their allocations on every exit path. Signed-off-by: Mohammed Mustafa <[email protected]> --- v2: Don't use the cleanup attribute. Free explicitly on all exit paths. Free the original array pointer, not the advanced one. Drop the free_ptr move. src/readelf.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/readelf.c b/src/readelf.c --- a/src/readelf.c +++ b/src/readelf.c @@ -10068,6 +10068,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 +10132,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 +10142,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_base = xmalloc ((nculist + 1) * sizeof (*cus_base)); + struct mac_culist *cus = cus_base; /* Add sentinel. */ cus[nculist].offset = data->d_size; cus[nculist].files = (Dwarf_Files *) -1l; @@ -10142,8 +10152,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 @@ -10172,7 +10184,7 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), printf (_("\ %*s*** non-terminated string at end of section"), level, ""); - return; + goto out; } if (opcode == DW_MACINFO_define) @@ -10199,7 +10211,7 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), printf (_("\ %*s*** missing DW_MACINFO_start_file argument at end of section"), level, ""); - return; + goto out; } get_uleb128 (u128_2, readp, readendp); @@ -10241,6 +10253,9 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), break; } } + + out: + free (cus_base); } @@ -10282,7 +10297,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; @@ -10304,7 +10319,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), { invalid_data: error (0, 0, _("invalid data")); - return; + goto out; } const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp); printf (_(" Version: %" PRIu16 "\n"), vers); @@ -10314,7 +10329,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), if (vers != 4 && vers != 5) { printf (_(" unknown version, cannot parse section\n")); - return; + goto out; } if (readp + 1 > readendp) @@ -10526,6 +10541,9 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), putchar_unlocked ('\n'); } } + + out: + free_mac_culist (culist); }
