From: Sujal Tuladhar Date: Wed, 24 Jun 2026 16:22:34 +0000 (+0545) Subject: readelf: Fix heap-buffer-overflow reading .debug_cu_index size table X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=11f4264a7226e108d3e99073f2f469190a71eea4;p=thirdparty%2Felfutils.git readelf: Fix heap-buffer-overflow reading .debug_cu_index size table print_cu_index_section validated the .debug_cu_index/.debug_tu_index size table against dataend using only a single row: lengths_end = lengths + section_count * 4; but the size-table print loop iterates one row per used unit, with prow = lengths + (row - 1) * section_count * 4 for row up to unit_count, reading up to lengths + unit_count * section_count * 4. For unit_count >= 2 this reads (unit_count - 1) * section_count * 4 bytes past the validated end of the section -- a heap-buffer-overflow read reachable from a crafted .dwp/ELF via 'eu-readelf --debug-dump=cu_index FILE' (or 'eu-readelf -w'). The offset table is not affected: its extent (unit_count * section_count * off_bytes, which equals lengths) is already validated against dataend. Size lengths_end over all unit_count rows to match, and guard the multiplication against overflow. * src/readelf.c (print_cu_index_section): Size the size table over all unit_count rows; add an overflow guard. https://sourceware.org/bugzilla/show_bug.cgi?id=34317 Signed-off-by: Sujal Tuladhar --- diff --git a/src/readelf.c b/src/readelf.c index 0258d41a..8d7950d3 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -12332,7 +12332,10 @@ print_cu_index_section (Dwfl_Module *dwflmod __attribute__ ((unused)), /* Size slots for each section follow the offsets (used rows). */ const unsigned char *lengths = (offsets + unit_count * section_count * off_bytes); - const unsigned char *lengths_end = lengths + section_count * 4; + /* The size table has one row of section_count 4-byte slots per unit, + just like the offset table, so it spans unit_count rows (not one). */ + const unsigned char *lengths_end = (lengths + + unit_count * section_count * 4); /* Sanity check the above against dataend. */ if ((slot_count > UINT32_MAX / 8) @@ -12340,6 +12343,8 @@ print_cu_index_section (Dwfl_Module *dwflmod __attribute__ ((unused)), || (unit_count > SIZE_MAX / off_bytes) || ((unit_count != 0) && (section_count > SIZE_MAX / unit_count)) || ((section_count != 0) && (unit_count > SIZE_MAX / section_count)) + || ((unit_count != 0) + && (section_count > SIZE_MAX / (4 * (size_t) unit_count))) || (indices > dataend) || (sections > dataend) || (offsets > dataend)