llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Yao Qi (qiyao)
<details>
<summary>Changes</summary>
The empty-stack branch of `Evaluate_DW_OP_piece` resizes a `Value`'s data
buffer to the piece byte size and then `memset`s that many bytes:
```
curr_piece.ResizeData(piece_byte_size);
::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size);
```
The `piece_byte_size` is an untrusted DWARF operand, and the resize result
is never checked. `DataBufferHeap::SetByteSize` silently leaves the
buffer empty when the requested size cannot be allocated, so a huge
`DW_OP_piece` operand produces a `memset` over an unallocated buffer: a
wild write. ASan reports it as a wild write from the
lldb-dwarf-expression-fuzzer; even without ASan it faults. The unit test
feeds a `DW_OP_piece` whose ULEB128 operand encodes `INT64_MAX`:
```
[ RUN ] DWARFExpression.DW_OP_piece_empty_stack_huge_size
#<!-- -->2 SignalHandler(int, __siginfo*, void*)
#<!-- -->4 DWARFExpression::Evaluate(...)
```
(SIGSEGV, the process aborts.)
Verify `ResizeData` actually produced the requested size and return an
error otherwise, matching the existing check in the load-address piece
path.
Adds `DWARFExpression.DW_OP_piece_empty_stack_huge_size`, which crashes
(SIGSEGV / ASan wild write) without the fix.
---
Full diff: https://github.com/llvm/llvm-project/pull/207009.diff
2 Files Affected:
- (modified) lldb/source/Expression/DWARFExpression.cpp (+4-1)
- (modified) lldb/unittests/Expression/DWARFExpressionTest.cpp (+9)
``````````diff
diff --git a/lldb/source/Expression/DWARFExpression.cpp
b/lldb/source/Expression/DWARFExpression.cpp
index 5a3c99caeb1bb..90c61b2ff89eb 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1085,7 +1085,10 @@ static llvm::Error Evaluate_DW_OP_piece(EvalContext
&eval_ctx,
// In a multi-piece expression, this means that the current piece is
// not available. Fill with zeros for now by resizing the data and
// appending it
- curr_piece.ResizeData(piece_byte_size);
+ if (curr_piece.ResizeData(piece_byte_size) != piece_byte_size)
+ return llvm::createStringError(
+ "failed to resize the piece buffer to %" PRIu64 " bytes",
+ piece_byte_size);
// Note that "0" is not a correct value for the unknown bits.
// It would be better to also return a mask of valid bits together
// with the expression result, so the debugger can print missing
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp
b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 305c4af2582db..829e490213194 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -617,6 +617,15 @@ TEST(DWARFExpression, DW_OP_piece) {
ExpectHostAddress(expected_host_buffer));
}
+TEST(DWARFExpression, DW_OP_piece_empty_stack_huge_size) {
+ // An empty-stack DW_OP_piece with a byte size that cannot be allocated must
+ // report an error. The ULEB128 operand here encodes INT64_MAX.
+ EXPECT_THAT_ERROR(Evaluate({DW_OP_piece, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x7f})
+ .takeError(),
+ llvm::Failed());
+}
+
TEST(DWARFExpression, DW_OP_implicit_value) {
unsigned char bytes = 4;
``````````
</details>
https://github.com/llvm/llvm-project/pull/207009
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits