https://github.com/kastiglione updated https://github.com/llvm/llvm-project/pull/211042
>From 6e3b34d77976e1b30371e5d4401f9a034708f68e Mon Sep 17 00:00:00 2001 From: Dave Lee <[email protected]> Date: Tue, 21 Jul 2026 09:35:27 -0700 Subject: [PATCH 1/2] [lldb][test] Reinforce formatter bytecode unit tests --- .../DataFormatter/FormatterBytecodeTest.cpp | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp b/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp index 20c90bfe6fb60..6c361db813bee 100644 --- a/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp +++ b/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp @@ -251,6 +251,64 @@ TEST_F(FormatterBytecodeTest, ArithOps) { } } +TEST_F(FormatterBytecodeTest, OutOfBounds) { + { + // op_lit_uint's ULEB128 operand is truncated: the interpreter runs off + // the end of the buffer while decoding it. + DataStack data; + ASSERT_FALSE(Interpret({op_lit_uint}, data)); + } + { + // op_begin claims a block that is longer than the remaining bytecode. + DataStack data; + ASSERT_FALSE(Interpret({op_begin, 5, op_lit_uint, 42}, data)); + } + { + // The ULEB128 byte's continuation bit is set, but there is no + // terminating byte. + DataStack data; + ASSERT_FALSE(Interpret({op_lit_uint, 0x80}, data)); + } + { + // Same as above, but for op_lit_int's SLEB128 operand. + DataStack data; + ASSERT_FALSE(Interpret({op_lit_int, 0x80}, data)); + } + { + // The ULEB128 operand encodes a value that doesn't fit into a uint64_t: + // 9 continuation bytes (63 bits) followed by a final byte contributing + // more than the single remaining bit. + DataStack data; + ASSERT_FALSE(Interpret({op_lit_uint, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x02}, + data)); + } + { + // Same as above, but for op_lit_int's SLEB128 operand not fitting into + // an int64_t. + DataStack data; + ASSERT_FALSE(Interpret({op_lit_int, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x02}, + data)); + } +} + +TEST_F(FormatterBytecodeTest, EmptyBytecode) { + DataStack data; + ASSERT_TRUE(Interpret({}, data)); + ASSERT_EQ(data.size(), 0u); +} + +TEST_F(FormatterBytecodeTest, UnknownSelector) { + DataStack data; + ASSERT_FALSE(Interpret({op_lit_selector, 0xff, op_call}, data)); +} + +TEST_F(FormatterBytecodeTest, UnknownOpcode) { + DataStack data; + ASSERT_FALSE(Interpret({0xaa}, data)); +} + TEST_F(FormatterBytecodeTest, CallOps) { { DataStack data; >From 67ab2ad74dc87fff51afa5378a3ae64dddc5a292 Mon Sep 17 00:00:00 2001 From: Dave Lee <[email protected]> Date: Tue, 21 Jul 2026 15:53:13 -0700 Subject: [PATCH 2/2] Assert error messages for failure cases --- .../DataFormatter/FormatterBytecodeTest.cpp | 104 ++++++++++-------- 1 file changed, 59 insertions(+), 45 deletions(-) diff --git a/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp b/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp index 6c361db813bee..b8675f92d1f30 100644 --- a/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp +++ b/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp @@ -1,17 +1,20 @@ #include "lldb/DataFormatters/FormatterBytecode.h" #include "lldb/Utility/StreamString.h" +#include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" using namespace lldb_private; using namespace lldb; using namespace FormatterBytecode; +using llvm::FailedWithMessage; using llvm::StringRef; namespace { class FormatterBytecodeTest : public ::testing::Test {}; +} // namespace -bool Interpret(std::vector<uint8_t> code, DataStack &data) { +static bool Interpret(std::vector<uint8_t> code, DataStack &data) { auto buf = StringRef(reinterpret_cast<const char *>(code.data()), code.size()); ControlStack control({buf}); @@ -26,7 +29,15 @@ bool Interpret(std::vector<uint8_t> code, DataStack &data) { return true; } -} // namespace +/// Like Interpret() above, but returns (instead of discarding) the Error, +/// allowing tests to assert on the error message. +static llvm::Error InterpretFail(std::vector<uint8_t> code) { + auto buf = + StringRef(reinterpret_cast<const char *>(code.data()), code.size()); + ControlStack control({buf}); + DataStack data; + return Interpret(control, data, sig_summary); +} TEST_F(FormatterBytecodeTest, StackOps) { { @@ -252,45 +263,48 @@ TEST_F(FormatterBytecodeTest, ArithOps) { } TEST_F(FormatterBytecodeTest, OutOfBounds) { - { - // op_lit_uint's ULEB128 operand is truncated: the interpreter runs off - // the end of the buffer while decoding it. - DataStack data; - ASSERT_FALSE(Interpret({op_lit_uint}, data)); - } - { - // op_begin claims a block that is longer than the remaining bytecode. - DataStack data; - ASSERT_FALSE(Interpret({op_begin, 5, op_lit_uint, 42}, data)); - } - { - // The ULEB128 byte's continuation bit is set, but there is no - // terminating byte. - DataStack data; - ASSERT_FALSE(Interpret({op_lit_uint, 0x80}, data)); - } - { - // Same as above, but for op_lit_int's SLEB128 operand. - DataStack data; - ASSERT_FALSE(Interpret({op_lit_int, 0x80}, data)); - } - { - // The ULEB128 operand encodes a value that doesn't fit into a uint64_t: - // 9 continuation bytes (63 bits) followed by a final byte contributing - // more than the single remaining bit. - DataStack data; - ASSERT_FALSE(Interpret({op_lit_uint, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x02}, - data)); - } - { - // Same as above, but for op_lit_int's SLEB128 operand not fitting into - // an int64_t. - DataStack data; - ASSERT_FALSE(Interpret({op_lit_int, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x02}, - data)); - } + // op_lit_uint's ULEB128 operand is truncated: the interpreter runs off + // the end of the buffer while decoding it. + EXPECT_THAT_ERROR( + InterpretFail({op_lit_uint}), + FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " + "malformed uleb128, extends past end")); + + // op_begin claims a block that is longer than the remaining bytecode. + EXPECT_THAT_ERROR( + InterpretFail({op_begin, 5, op_lit_uint, 42}), + FailedWithMessage( + "unexpected end of data at offset 0x4 while reading [0x2, 0x7)")); + + // The ULEB128 byte's continuation bit is set, but there is no + // terminating byte. + EXPECT_THAT_ERROR( + InterpretFail({op_lit_uint, 0x80}), + FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " + "malformed uleb128, extends past end")); + + // Same as above, but for op_lit_int's SLEB128 operand. + EXPECT_THAT_ERROR( + InterpretFail({op_lit_int, 0x80}), + FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " + "malformed sleb128, extends past end")); + + // The ULEB128 operand encodes a value that doesn't fit into a uint64_t: + // 9 continuation bytes (63 bits) followed by a final byte contributing + // more than the single remaining bit. + EXPECT_THAT_ERROR( + InterpretFail({op_lit_uint, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x02}), + FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " + "uleb128 too big for uint64")); + + // Same as above, but for op_lit_int's SLEB128 operand not fitting into + // an int64_t. + EXPECT_THAT_ERROR( + InterpretFail({op_lit_int, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x02}), + FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " + "sleb128 too big for int64")); } TEST_F(FormatterBytecodeTest, EmptyBytecode) { @@ -300,13 +314,13 @@ TEST_F(FormatterBytecodeTest, EmptyBytecode) { } TEST_F(FormatterBytecodeTest, UnknownSelector) { - DataStack data; - ASSERT_FALSE(Interpret({op_lit_selector, 0xff, op_call}, data)); + EXPECT_THAT_ERROR(InterpretFail({op_lit_selector, 0xff, op_call}), + FailedWithMessage("{0} (opcode={1}, selector={2})")); } TEST_F(FormatterBytecodeTest, UnknownOpcode) { - DataStack data; - ASSERT_FALSE(Interpret({0xaa}, data)); + EXPECT_THAT_ERROR(InterpretFail({0xaa}), + FailedWithMessage("opcode not implemented(opcode=170)")); } TEST_F(FormatterBytecodeTest, CallOps) { _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
