Author: Andy Yankovsky Date: 2022-02-09T17:38:38+01:00 New Revision: afb446e8a61de4a41504a71f61a4b1d93ce22716
URL: https://github.com/llvm/llvm-project/commit/afb446e8a61de4a41504a71f61a4b1d93ce22716 DIFF: https://github.com/llvm/llvm-project/commit/afb446e8a61de4a41504a71f61a4b1d93ce22716.diff LOG: [lldb] Constant-resolve operands to `getelementptr` Operands to `getelementptr` can be constants or constant expressions. Check that all operands can be constant-resolved and resolve them during the evaluation. If some operands can't be resolved as constants -- the expression evaluation will fallback to JIT. Fixes: https://bugs.llvm.org/show_bug.cgi?id=52449 Reviewed By: #lldb, shafik Differential Revision: https://reviews.llvm.org/D113498 Added: Modified: lldb/source/Expression/IRInterpreter.cpp lldb/test/API/lang/cpp/static_members/TestCPPStaticMembers.py Removed: ################################################################################ diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index 21348be1578ff..2ad51d0e84027 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -285,9 +285,11 @@ class InterpreterStackFrame { return true; // no offset to apply! SmallVector<Value *, 8> indices(op_cursor, op_end); - Type *src_elem_ty = cast<GEPOperator>(constant_expr)->getSourceElementType(); + + // DataLayout::getIndexedOffsetInType assumes the indices are + // instances of ConstantInt. uint64_t offset = m_target_data.getIndexedOffsetInType(src_elem_ty, indices); @@ -466,12 +468,20 @@ static bool CanResolveConstant(llvm::Constant *constant) { case Instruction::BitCast: return CanResolveConstant(constant_expr->getOperand(0)); case Instruction::GetElementPtr: { + // Check that the base can be constant-resolved. ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin(); Constant *base = dyn_cast<Constant>(*op_cursor); - if (!base) + if (!base || !CanResolveConstant(base)) return false; - return CanResolveConstant(base); + // Check that all other operands are just ConstantInt. + for (Value *op : make_range(constant_expr->op_begin() + 1, + constant_expr->op_end())) { + ConstantInt *constant_int = dyn_cast<ConstantInt>(op); + if (!constant_int) + return false; + } + return true; } } } else { diff --git a/lldb/test/API/lang/cpp/static_members/TestCPPStaticMembers.py b/lldb/test/API/lang/cpp/static_members/TestCPPStaticMembers.py index 07ec5c52ea4c7..503e0d1341566 100644 --- a/lldb/test/API/lang/cpp/static_members/TestCPPStaticMembers.py +++ b/lldb/test/API/lang/cpp/static_members/TestCPPStaticMembers.py @@ -41,3 +41,31 @@ def test_access_without_scope(self): self.createTestTarget() self.expect("expression s_c", error=True, startstr="error: use of undeclared identifier 's_d'") + + def test_no_crash_in_IR_arithmetic(self): + """ + Test that LLDB doesn't crash on evaluating specific expression involving + pointer arithmetic and taking the address of a static class member. + See https://bugs.llvm.org/show_bug.cgi?id=52449 + """ + self.build() + lldbutil.run_to_source_breakpoint(self, "// stop in main", lldb.SBFileSpec("main.cpp")) + + # This expression contains the following IR code: + # ... i64 ptrtoint (i32* @_ZN1A3s_cE to i64)) ... + expr = "(int*)100 + (long long)(&A::s_c)" + + # The IR interpreter doesn't support non-const operands to the + # `GetElementPtr` IR instruction, so verify that it correctly fails to + # evaluate expression. + opts = lldb.SBExpressionOptions() + opts.SetAllowJIT(False) + value = self.target().EvaluateExpression(expr, opts) + self.assertTrue(value.GetError().Fail()) + self.assertIn( + "Can't evaluate the expression without a running target", + value.GetError().GetCString()) + + # Evaluating the expression via JIT should work fine. + value = self.target().EvaluateExpression(expr) + self.assertSuccess(value.GetError()) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits