Hi Sayed, On Thu, Jul 23, 2026 at 12:17:48PM +0530, Sayed Kaif wrote: > read_line_header parses the DWARF line program header but never checks > the header_length field against the bounds of the unit. read_srcfiles > then does > > lineendp = lh->header_start + lh->header_length; > > and uses that pointer as the upper bound while scanning the directory and > file-name tables (and read_srclines similarly computes > lh->header_start + lh->header_length as the start of the line program).
Which depends on header_length having been validated... > A .debug_line unit whose header_length is larger than the remaining unit > data therefore makes lineendp point past the end of the section, and the > directory scan reads out of bounds: > > ERROR: AddressSanitizer: heap-buffer-overflow ... READ of size 2 > #0 __interceptor_memchr > #1 read_srcfiles libdw/dwarf_getsrclines.c:373 > #2 get_lines_or_files libdw/dwarf_getsrclines.c:1353 > #3 __libdw_getsrcfiles libdw/dwarf_getsrclines.c:1425 > #4 dwarf_getsrcfiles libdw/dwarf_getsrcfiles.c:105 > 0 bytes to the right of 17-byte region > > header_length counts the bytes from directly after the field to the > start of the line number program, so it must fit within the unit (which > read_line_header has already bounded to the section via unit_length). > Reject a header_length that exceeds the remaining unit bytes, turning the > crafted input into a clean DWARF_E_INVALID_DEBUG_LINE error. Valid > DWARF is unaffected. Nice find. > Signed-off-by: Sayed Kaif <[email protected]> > --- > diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c > index 3521511..1d5f659 100644 > --- a/libdw/dwarf_getsrclines.c > +++ b/libdw/dwarf_getsrclines.c > @@ -246,6 +246,15 @@ read_line_header (Dwarf *dbg, unsigned address_size, > } > lh->header_start = linep; > > + /* The header length is the number of bytes from here to the start of > + the line number program, so it must stay within the unit (and thus > + the section). Without this check a bogus header_length makes > + read_srcfiles/read_srclines compute an out-of-bounds end pointer > + (header_start + header_length) and read past the section while > + parsing the directory and file tables. */ > + if (unlikely (lh->header_length > (size_t) (lineendp - linep))) > + goto invalid_data; Looks like the correct sanity check. Pushed as https://sourceware.org/cgit/elfutils/commit/?id=0845f5cea2ab Thanks, Mark
