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

Reply via email to