Hi, The attached patch fixes a NULL pointer dereference in eu-readelf's print_debug_units when printing a .debug_types section for which libdw has no section data.
For .debug_types, print_debug_units builds a fake Dwarf_CU ending at sectiondata[IDX_debug_info]->d_size so that dwarf_get_units moves on to the first type unit. When dwfl_module_getdwarf fails, readelf uses its zeroed dummy_dbg and still prints any section named .debug_types, so this dereferences NULL; libdw also accepts .debug_types with .debug_line but no .debug_info. The patch returns through the existing cleanup when there is no .debug_types data, and starts the fake CU at the beginning of .debug_types when there is no .debug_info. Reproducible with eu-readelf --debug-dump=info on a crafted ELF with a .debug_types section that libdw cannot load; ASAN reports a SEGV on address 0x10 in print_debug_units. The patch (git format-patch, applies on HEAD 10b728d8) is attached. I can send the reproducer file, or add it as a test case, if that helps. Thanks, Sujal Tuladhar
From 4bcddbe16afb71f98b2a4cda4ad06bfd4b71d87c Mon Sep 17 00:00:00 2001 From: Sujal Tuladhar <[email protected]> Date: Thu, 5 Nov 2026 08:08:23 +0000 Subject: [PATCH] readelf: handle missing .debug_info and .debug_types data in print_debug_units When printing .debug_types, print_debug_units sets up a fake Dwarf_CU that ends at the end of .debug_info, so that dwarf_get_units continues with the first type unit: cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size; This dereferences NULL when libdw has no .debug_info data. That happens when dwfl_module_getdwarf fails and readelf falls back to its zeroed dummy_dbg while the file still has a section named .debug_types. libdw also accepts a file with .debug_types and .debug_line but no .debug_info, because valid_p only requires one of .debug_info, .debug_line or .debug_frame. With no .debug_types data, dwarf_get_units would then dereference sectiondata[IDX_debug_types] as well. Return when libdw has no .debug_types data, and start the fake CU at the beginning of .debug_types when there is no .debug_info. Reproducible with eu-readelf --debug-dump=info on a crafted ELF with a .debug_types section that libdw cannot load. AddressSanitizer reports a SEGV on address 0x10 in print_debug_units. * src/readelf.c (print_debug_units): Return when there is no .debug_types data and handle a missing .debug_info. Signed-off-by: Sujal Tuladhar <[email protected]> --- src/readelf.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/readelf.c b/src/readelf.c index 4e4f643a..9da1c048 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -8690,9 +8690,22 @@ print_debug_units (Dwfl_Module *dwflmod, Dwarf_CU is still in the expected section. */ if (debug_types) { + /* libdw ignores a section it cannot use, e.g. an empty one or one + that failed to decompress. Then there is nothing to print. */ + if (dbg->sectiondata[IDX_debug_types] == NULL) + goto do_return; cu_mem.dbg = dbg; - cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size; - cu_mem.sec_idx = IDX_debug_info; + if (dbg->sectiondata[IDX_debug_info] != NULL) + { + cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size; + cu_mem.sec_idx = IDX_debug_info; + } + else + { + /* No .debug_info, start at the beginning of .debug_types. */ + cu_mem.end = 0; + cu_mem.sec_idx = IDX_debug_types; + } cu = &cu_mem; } else -- 2.43.0
