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

Reply via email to