diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -1655,11 +1655,16 @@ case DW_OP_skip: { int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); lldb::offset_t new_offset = offset + skip_offset; - if (opcodes.ValidOffset(new_offset)) + // New offset can point at the end of the data, in this case we should + // terminate the DWARF expression evaluation (will happen in the loop + // condition). + if (new_offset <= opcodes.GetByteSize()) offset = new_offset; else { if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip."); + error_ptr->SetErrorStringWithFormatv( + "Invalid opcode offset in DW_OP_skip: {0}+({1}) > {2}", offset, + skip_offset, opcodes.GetByteSize()); return false; } } break; @@ -1684,11 +1689,16 @@ Scalar zero(0); if (tmp.ResolveValue(exe_ctx) != zero) { lldb::offset_t new_offset = offset + bra_offset; - if (opcodes.ValidOffset(new_offset)) + // New offset can point at the end of the data, in this case we should + // terminate the DWARF expression evaluation (will happen in the loop + // condition). + if (new_offset <= opcodes.GetByteSize()) offset = new_offset; else { if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra."); + error_ptr->SetErrorStringWithFormatv( + "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset, + bra_offset, opcodes.GetByteSize()); return false; } } diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -131,6 +131,25 @@ llvm::HasValue(0xffff010101010101)); } +TEST(DWARFExpression, DW_OP_skip) { + EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u, 0x42, DW_OP_skip, 0x02, 0x00, + DW_OP_const1u, 0xff}), + llvm::HasValue(0x42)); +} + +TEST(DWARFExpression, DW_OP_bra) { + EXPECT_THAT_EXPECTED( + // clang-format off + Evaluate({ + DW_OP_const1u, 0x42, // push 0x42 + DW_OP_const1u, 0x1, // push 0x1 + DW_OP_bra, 0x02, 0x00, // if 0x1 > 0, then skip 0x0002 opcodes + DW_OP_const1u, 0xff, // push 0xff + }), + // clang-format on + llvm::HasValue(0x42)); +} + TEST(DWARFExpression, DW_OP_convert) { /// Auxiliary debug info. const char *yamldata = R"(