Issue 202293
Summary [lldb] misparse DWARF expressions after oversized LEB128 operands
Labels
Assignees
Reporter firmiana402
    ## Summary

I found that LLDB/LLVM's DWARF _expression_ parser can mishandle oversized LEB128 operands.

The issue is not limited to a single opcode. Any DWARF _expression_ opcode whose operand is encoded as ULEB128 or SLEB128 can be affected if the encoded value does not fit in the parser's current `uint64_t` / `int64_t` representation.

In that case, the LEB decode error is not surfaced cleanly by `DWARFExpression::Operation::extract` (in [llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp](https://github.com/llvm/llvm-project/blob/main/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp)) . The operand may be treated as zero while the parser does not consume the full LEB payload. This can desynchronize the _expression_ stream and cause later payload bytes to be interpreted as DWARF opcodes.

## Minimal Case

I am using a raw DWARF _expression_ here because this issue is about DWARF operand decoding itself, and the reduced form is clearer than a source-level reproducer.

One minimal case is:

```text
DW_OP_constu [0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x02]
# the ULEB128 payload encodes 2^64, so on a 64-bit target it should truncate to 0
DW_OP_lit0
DW_OP_eq
DW_OP_stack_value
```

On a 64-bit target, `2^64` should truncate to generic zero, so the _expression_ should behave exactly like:

```text
DW_OP_constu 0
DW_OP_lit0
DW_OP_eq
DW_OP_stack_value
```

and therefore evaluate to `1`.

GDB executes this correctly and produces the final result `1`.

LLDB does not. Instead, it reports:

```text
<Unhandled opcode DW_OP_unknown_2 in DWARFExpression>
```

This strongly suggests that LLDB is not consuming the full, complete LEB payload. The terminating byte `0x02` appears to be left behind and then treated as the next DWARF opcode.

The same issue reproduces for `DW_OP_consts` with the same byte sequence interpreted as a legal SLEB128 encoding of `+2^64`.

## Affected Opcodes

This can affect any DWARF _expression_ opcode with ULEB128 or SLEB128 operands.

## Source-Level Cause
`DWARFExpression::Operation::extract` (in [llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp](https://github.com/llvm/llvm-project/blob/main/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp)) decodes LEB operands through:

```cpp
Data.getULEB128(&Offset)
Data.getSLEB128(&Offset)
```

without passing an Error.

If decodeULEB128 / decodeSLEB128 detects that the value is too large for `uint64_t` / `int64_t`, the error is not surfaced. The helper returns zero, and the offset may not be advanced to the end of the LEB payload. Operation::extract then records the stale offset as the operation end and returns success, causing the next iterator step to parse from the wrong byte.

## Expected Behavior
For `DW_OP_constu` / `DW_OP_consts`, LLDB should consume the full well-formed LEB128 payload and truncate the value to the target generic stack element size.

For other LEB-operand opcodes where truncation is not valid, LLDB should report a clean decode error instead of desynchronizing the _expression_ parser.

## Potential Fix Direction
The fix likely needs to:

- Make Operation::extract detect and propagate LEB128 decode errors.
- Special-case generic constant operations such as `DW_OP_constu` and `DW_OP_consts` so that oversized well-formed constants are fully consumed and truncated instead of rejected.
- Ensure no LEB decode path leaves the _expression_ iterator pointing into the middle of a LEB payload.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to