[Lldb-commits] [lldb] [lldb] Reject mixed typed DWARF binary operands (PR #201288)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Jun 3 20:01:24 PDT 2026
https://github.com/firmiana402 updated https://github.com/llvm/llvm-project/pull/201288
>From f1b02e03761213e92d2e782c0b367d9d56cd240a Mon Sep 17 00:00:00 2001
From: firmiana402 <firmiana402 at gmail.com>
Date: Wed, 3 Jun 2026 11:31:09 +0800
Subject: [PATCH 1/2] [lldb] Reject mixed typed DWARF binary operands
---
lldb/source/Expression/DWARFExpression.cpp | 90 ++++++++++++++++++++++
1 file changed, 90 insertions(+)
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 106e3b4d59283..c04fcc34b7dfa 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1291,6 +1291,32 @@ static llvm::Error Evaluate_DW_OP_call_frame_cfa(EvalContext &eval_ctx) {
return llvm::Error::success();
}
+static llvm::Error CheckScalarOperandsHaveSameType(const Scalar &lhs,
+ const Scalar &rhs,
+ LocationAtom opcode) {
+ // Scalar does not preserve the original DWARF DIE, but it does carry the
+ // pieces of base-type information used by the evaluator: kind, size, and
+ // integer signedness.
+ if (lhs.GetType() != rhs.GetType())
+ return llvm::createStringError(
+ "%s requires operands to have the same type",
+ DW_OP_value_to_name(opcode));
+
+ if (lhs.GetByteSize() != rhs.GetByteSize())
+ return llvm::createStringError(
+ "%s requires operands to have the same type",
+ DW_OP_value_to_name(opcode));
+
+ // Floating scalars do not have integer signedness, so only compare
+ // signedness after establishing that both operands are integers.
+ if (lhs.GetType() == Scalar::e_int && lhs.IsSigned() != rhs.IsSigned())
+ return llvm::createStringError(
+ "%s requires operands to have the same type",
+ DW_OP_value_to_name(opcode));
+
+ return llvm::Error::success();
+}
+
llvm::Expected<Value> DWARFExpression::Evaluate(
ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
lldb::ModuleSP module_sp, const DataExtractor &opcodes,
@@ -1470,12 +1496,20 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
break;
case DW_OP_and:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() & tmp.GetScalar();
break;
case DW_OP_div: {
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
if (tmp.GetScalar().IsZero())
return llvm::createStringError("divide by zero");
@@ -1493,12 +1527,20 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
} break;
case DW_OP_minus:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() - tmp.GetScalar();
break;
case DW_OP_mod:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() % tmp.GetScalar();
@@ -1521,12 +1563,20 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
break;
case DW_OP_or:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() | tmp.GetScalar();
break;
case DW_OP_plus:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() += tmp.GetScalar();
@@ -1541,12 +1591,20 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
} break;
case DW_OP_shl:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() <<= tmp.GetScalar();
break;
case DW_OP_shr:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
if (!stack.back().GetScalar().ShiftRightLogical(tmp.GetScalar()))
@@ -1554,12 +1612,20 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
break;
case DW_OP_shra:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() >>= tmp.GetScalar();
break;
case DW_OP_xor:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() ^ tmp.GetScalar();
@@ -1601,36 +1667,60 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
} break;
case DW_OP_eq:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() == tmp.GetScalar();
break;
case DW_OP_ge:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() >= tmp.GetScalar();
break;
case DW_OP_gt:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() > tmp.GetScalar();
break;
case DW_OP_le:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() <= tmp.GetScalar();
break;
case DW_OP_lt:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() < tmp.GetScalar();
break;
case DW_OP_ne:
+ if (llvm::Error err = CheckScalarOperandsHaveSameType(
+ stack[stack.size() - 2].GetScalar(), stack.back().GetScalar(),
+ opcode))
+ return err;
tmp = stack.back();
stack.pop_back();
stack.back().GetScalar() = stack.back().GetScalar() != tmp.GetScalar();
>From dd117340160e242853d09b2c57477de6d762c243 Mon Sep 17 00:00:00 2001
From: firmiana402 <firmiana402 at gmail.com>
Date: Thu, 4 Jun 2026 11:00:50 +0800
Subject: [PATCH 2/2] [lldb] Test mixed typed DWARF binary operands
---
.../Expression/DWARFExpressionTest.cpp | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 00ee6b13ad93c..ddbbdc91711ff 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -576,6 +576,54 @@ TEST(DWARFExpression, DW_OP_convert) {
llvm::Failed());
}
+TEST(DWARFExpression, TypedBinaryOpsRejectMismatchedTypes) {
+ class TypedDwarfDelegate : public MockDwarfDelegate {
+ public:
+ enum : uint8_t {
+ UnsignedChar = 1,
+ SignedChar = 2,
+ UnsignedShort = 3,
+ };
+
+ llvm::Expected<std::pair<uint64_t, bool>>
+ GetDIEBitSizeAndSign(uint64_t relative_die_offset) const override {
+ switch (relative_die_offset) {
+ case UnsignedChar:
+ return std::pair<uint64_t, bool>{8, false};
+ case SignedChar:
+ return std::pair<uint64_t, bool>{8, true};
+ case UnsignedShort:
+ return std::pair<uint64_t, bool>{16, false};
+ default:
+ return llvm::createStringError("unknown base type offset");
+ }
+ }
+ };
+
+ TypedDwarfDelegate unit;
+ constexpr uint8_t opcodes[] = {
+ DW_OP_plus, DW_OP_minus, DW_OP_div, DW_OP_mod, DW_OP_and, DW_OP_or,
+ DW_OP_xor, DW_OP_shl, DW_OP_shr, DW_OP_shra, DW_OP_lt, DW_OP_le,
+ DW_OP_gt, DW_OP_ge, DW_OP_eq, DW_OP_ne,
+ };
+
+ for (uint8_t opcode : opcodes) {
+ std::vector<uint8_t> expr = {
+ DW_OP_constu, 0xff, 0x01, DW_OP_convert,
+ TypedDwarfDelegate::UnsignedChar, DW_OP_lit1, DW_OP_convert,
+ TypedDwarfDelegate::UnsignedShort, opcode, DW_OP_stack_value};
+ EXPECT_THAT_EXPECTED(Evaluate(expr, {}, &unit), llvm::Failed())
+ << "opcode 0x" << llvm::utohexstr(opcode);
+ }
+
+ EXPECT_THAT_EXPECTED(
+ Evaluate({DW_OP_constu, 0xff, 0x01, DW_OP_convert,
+ TypedDwarfDelegate::UnsignedChar, DW_OP_lit1, DW_OP_convert,
+ TypedDwarfDelegate::SignedChar, DW_OP_plus, DW_OP_stack_value},
+ {}, &unit),
+ llvm::Failed());
+}
+
TEST(DWARFExpression, DW_OP_stack_value) {
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_stack_value}), llvm::Failed());
}
More information about the lldb-commits
mailing list