]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: Fix out-of-bounds read in CFI DW_CFA_advance_loc1 handling
authorSayed Kaif <skaif@digiscrypt.com>
Mon, 6 Jul 2026 07:12:35 +0000 (12:42 +0530)
committerMark Wielaard <mark@klomp.org>
Mon, 6 Jul 2026 09:15:24 +0000 (11:15 +0200)
execute_cfi walks a CFI instruction stream delimited by program and end.
The outer loop condition (program < end) only guarantees that the opcode
byte is present.  The DW_CFA_advance_loc1 case then reads a one-byte
operand with

  operand = *program++;

without first checking that another byte is available.  The sibling
cases DW_CFA_advance_loc2/4/8 all guard their fixed-size reads with
cfi_assert (program + N <= end), and readelf's own CFI printer guards
advance_loc1 with an equivalent check, but this path was missing it.

A crafted or truncated FDE/CIE whose instruction stream ends exactly on
a DW_CFA_advance_loc1 opcode therefore causes a one-byte read past the
end of the CFI data buffer.  Add the matching bounds check so malformed
input is rejected with DWARF_E_INVALID_CFI instead.

Signed-off-by: Sayed Kaif <skaif@digiscrypt.com>
libdw/cfi.c

index 743bfc073a4a23a44c2e5b5f95984c611df9a338..a9607246c8d49bf4cca68e1b3183df097a9efae8 100644 (file)
@@ -146,6 +146,7 @@ execute_cfi (Dwarf_CFI *cache,
          /* These cases move LOC, i.e. "create a new table row".  */
 
        case DW_CFA_advance_loc1:
+         cfi_assert (program + 1 <= end);
          operand = *program++;
          FALLTHROUGH;
        case DW_CFA_advance_loc + 0 ... DW_CFA_advance_loc + CFI_PRIMARY_MAX: