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

Reply via email to