Hi, The attached patch fixes a heap out-of-bounds read in eu-readelf's print_debug_str_offsets_section when a .debug_str_offsets section ends 1 to 3 bytes after a table.
The initial 4-byte unit_length is read before checking that 4 bytes are left; the loop only guarantees readp < readendp. The DWARF64 length and the version/padding reads that follow are already checked. This is the readelf counterpart of PR 34383, which commit 6f8f78ce fixed only in libdw's str_offsets_base_off; the patch adds the same check to readelf. Reproducible with eu-readelf --debug-dump=str on a crafted ELF whose compressed .debug_str_offsets holds one valid table followed by 2 trailing bytes; ASAN reports a heap-buffer-overflow READ of size 4 at the unit_length read. 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 8128c9f86b0b4964a6104438418d47eb9c5fa0d5 Mon Sep 17 00:00:00 2001 From: Sujal Tuladhar <[email protected]> Date: Thu, 5 Nov 2026 08:08:23 +0000 Subject: [PATCH] readelf: check there are header bytes in print_debug_str_offsets_section print_debug_str_offsets_section reads the initial 4-byte unit_length of a DWARF 5 .debug_str_offsets table before checking that 4 bytes are left: unit_length = read_4ubyte_unaligned_inc (dbg, readp); The loop only guarantees readp < readendp, so when the section ends 1 to 3 bytes after a table, the read goes up to 3 bytes past the section data. The DWARF64 length and the version/padding reads that follow are already checked. Commit 6f8f78ce ("libdw: Check there are any header bytes in str_offsets_base_off") fixed the same read in libdw (PR 34383). Make the same check in readelf. Reproducible with eu-readelf --debug-dump=str on a crafted ELF whose compressed .debug_str_offsets holds one valid table followed by 2 trailing bytes. AddressSanitizer reports a heap-buffer-overflow READ of size 4 at the unit_length read. * src/readelf.c (print_debug_str_offsets_section): Check there are 4 bytes before reading the initial unit_length. Signed-off-by: Sujal Tuladhar <[email protected]> --- src/readelf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/readelf.c b/src/readelf.c index f632be0a..4e4f643a 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -11527,6 +11527,8 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)), uint16_t version; uint16_t padding; + if (unlikely (readendp - readp < 4)) + goto invalid_data; unit_length = read_4ubyte_unaligned_inc (dbg, readp); if (unlikely (unit_length == 0xffffffff)) { -- 2.43.0
