From: Sayed Kaif Date: Sun, 12 Jul 2026 05:14:46 +0000 (+0530) Subject: libdw: Fix out-of-bounds read in DW_FORM_indirect form length parsing X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f19bf3a9f1b199019b708737bbddda687457baa2;p=thirdparty%2Felfutils.git libdw: Fix out-of-bounds read in DW_FORM_indirect form length parsing __libdw_form_val_compute_len handles DW_FORM_indirect by reading the real form as an uleb128 and then computing the length of a value of that form. The guard that rejects a nested DW_FORM_indirect or a DW_FORM_implicit_const inspected *valp instead of the decoded form value u128. After get_uleb128 the cursor valp may point right at the end of the CU data (get_uleb128 advances up to the section end), so dereferencing *valp reads one byte past the buffer. A DW_FORM_indirect attribute whose inner form uleb128 ends exactly at cu->endp triggers a one-byte out-of-bounds read. This path is reached from dwarf_child() and dwarf_getattrs() while skipping attribute values, which rely on __libdw_form_val_len doing a safe bounds check. Besides the overread, comparing *valp (the first byte of the value data) rather than u128 (the form) is wrong: it can spuriously reject a valid attribute whose value happens to start with 0x16 or 0x21. Compare u128, which is already the decoded form and needs no further dereference. * libdw/libdw_form.c (__libdw_form_val_compute_len): Check the decoded form u128 instead of dereferencing *valp for the nested DW_FORM_indirect / DW_FORM_implicit_const guard. Signed-off-by: Sayed Kaif --- diff --git a/libdw/libdw_form.c b/libdw/libdw_form.c index 40045440..24622d7e 100644 --- a/libdw/libdw_form.c +++ b/libdw/libdw_form.c @@ -126,7 +126,7 @@ __libdw_form_val_compute_len (struct Dwarf_CU *cu, unsigned int form, if (valp >= endp) goto invalid; get_uleb128 (u128, valp, endp); - if (*valp == DW_FORM_indirect || *valp == DW_FORM_implicit_const) + if (u128 == DW_FORM_indirect || u128 == DW_FORM_implicit_const) return (size_t) -1; result = __libdw_form_val_len (cu, u128, valp); if (result != (size_t) -1)