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

Reply via email to