[llvm] efad149 - [Support] Add end/error to decode[US]LEB128AndInc
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 8 09:22:34 PDT 2024
Author: Fangrui Song
Date: 2024-05-08T09:22:30-07:00
New Revision: efad14954c9d5bdfaddaca948be6cd7e71a1d1b0
URL: https://github.com/llvm/llvm-project/commit/efad14954c9d5bdfaddaca948be6cd7e71a1d1b0
DIFF: https://github.com/llvm/llvm-project/commit/efad14954c9d5bdfaddaca948be6cd7e71a1d1b0.diff
LOG: [Support] Add end/error to decode[US]LEB128AndInc
Follow-up to #85739 to encourage error checking. We make `end` mandatory
and add decodeULEB128AndIncUnsafe to be used without `end`.
Pull Request: https://github.com/llvm/llvm-project/pull/90006
Added:
Modified:
llvm/include/llvm/Support/LEB128.h
llvm/unittests/Support/LEB128Test.cpp
llvm/utils/TableGen/DecoderEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Support/LEB128.h b/llvm/include/llvm/Support/LEB128.h
index c4e741549f3ff..a15b73bc14dcd 100644
--- a/llvm/include/llvm/Support/LEB128.h
+++ b/llvm/include/llvm/Support/LEB128.h
@@ -200,20 +200,26 @@ inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr,
return Value;
}
-inline uint64_t decodeULEB128AndInc(const uint8_t *&p) {
+inline uint64_t decodeULEB128AndInc(const uint8_t *&p, const uint8_t *end,
+ const char **error = nullptr) {
unsigned n;
- auto ret = decodeULEB128(p, &n);
+ auto ret = decodeULEB128(p, &n, end, error);
p += n;
return ret;
}
-inline int64_t decodeSLEB128AndInc(const uint8_t *&p) {
+inline int64_t decodeSLEB128AndInc(const uint8_t *&p, const uint8_t *end,
+ const char **error = nullptr) {
unsigned n;
- auto ret = decodeSLEB128(p, &n);
+ auto ret = decodeSLEB128(p, &n, end, error);
p += n;
return ret;
}
+inline uint64_t decodeULEB128AndIncUnsafe(const uint8_t *&p) {
+ return decodeULEB128AndInc(p, nullptr);
+}
+
/// Utility function to get the size of the ULEB128-encoded value.
extern unsigned getULEB128Size(uint64_t Value);
diff --git a/llvm/unittests/Support/LEB128Test.cpp b/llvm/unittests/Support/LEB128Test.cpp
index 08b8c5573ce63..60f5ddd568cad 100644
--- a/llvm/unittests/Support/LEB128Test.cpp
+++ b/llvm/unittests/Support/LEB128Test.cpp
@@ -155,6 +155,12 @@ TEST(LEB128Test, DecodeInvalidULEB128) {
EXPECT_NE(Error, nullptr); \
EXPECT_EQ(0ul, Actual); \
EXPECT_EQ(ERROR_OFFSET, ErrorOffset); \
+ Value = reinterpret_cast<const uint8_t *>(VALUE); \
+ Error = nullptr; \
+ Actual = decodeULEB128AndInc(Value, Value + strlen(VALUE), &Error); \
+ EXPECT_NE(Error, nullptr); \
+ EXPECT_EQ(0ul, Actual); \
+ EXPECT_EQ(ERROR_OFFSET, Value - reinterpret_cast<const uint8_t *>(VALUE)); \
} while (0)
// Buffer overflow.
@@ -224,6 +230,12 @@ TEST(LEB128Test, DecodeInvalidSLEB128) {
EXPECT_NE(Error, nullptr); \
EXPECT_EQ(0ul, Actual); \
EXPECT_EQ(ERROR_OFFSET, ErrorOffset); \
+ Value = reinterpret_cast<const uint8_t *>(VALUE); \
+ Error = nullptr; \
+ Actual = decodeSLEB128AndInc(Value, Value + strlen(VALUE), &Error); \
+ EXPECT_NE(Error, nullptr); \
+ EXPECT_EQ(0ul, Actual); \
+ EXPECT_EQ(ERROR_OFFSET, Value - reinterpret_cast<const uint8_t *>(VALUE)); \
} while (0)
// Buffer overflow.
@@ -246,7 +258,7 @@ TEST(LEB128Test, DecodeAndInc) {
#define EXPECT_LEB128(FUN, VALUE, SIZE) \
do { \
const uint8_t *V = reinterpret_cast<const uint8_t *>(VALUE), *P = V; \
- auto Expected = FUN(P), Actual = FUN##AndInc(P); \
+ auto Expected = FUN(P), Actual = FUN##AndInc(P, P + strlen(VALUE)); \
EXPECT_EQ(Actual, Expected); \
EXPECT_EQ(P - V, SIZE); \
} while (0)
@@ -255,6 +267,17 @@ TEST(LEB128Test, DecodeAndInc) {
EXPECT_LEB128(decodeSLEB128, "\x7f", 1);
EXPECT_LEB128(decodeSLEB128, "\x80\x01", 2);
#undef EXPECT_LEB128
+
+#define EXPECT_LEB128(FUN, VALUE, SIZE) \
+ do { \
+ const uint8_t *V = reinterpret_cast<const uint8_t *>(VALUE), *P = V; \
+ auto Expected = FUN(P), Actual = FUN##AndIncUnsafe(P); \
+ EXPECT_EQ(Actual, Expected); \
+ EXPECT_EQ(P - V, SIZE); \
+ } while (0)
+ EXPECT_LEB128(decodeULEB128, "\x7f", 1);
+ EXPECT_LEB128(decodeULEB128, "\x80\x01", 2);
+#undef EXPECT_LEB128
}
TEST(LEB128Test, SLEB128Size) {
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 3bd7f432ff9ad..c303322e63b44 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -2301,7 +2301,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
}
case MCD::OPC_CheckField: {
// Decode the start value.
- unsigned Start = decodeULEB128AndInc(++Ptr);
+ unsigned Start = decodeULEB128AndIncUnsafe(++Ptr);
unsigned Len = *Ptr;)";
if (IsVarLenInst)
OS << "\n makeUp(insn, Start + Len);";
@@ -2328,7 +2328,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
}
case MCD::OPC_CheckPredicate: {
// Decode the Predicate Index value.
- unsigned PIdx = decodeULEB128AndInc(++Ptr);
+ unsigned PIdx = decodeULEB128AndIncUnsafe(++Ptr);
// NumToSkip is a plain 24-bit integer.
unsigned NumToSkip = *Ptr++;
NumToSkip |= (*Ptr++) << 8;
@@ -2345,8 +2345,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
}
case MCD::OPC_Decode: {
// Decode the Opcode value.
- unsigned Opc = decodeULEB128AndInc(++Ptr);
- unsigned DecodeIdx = decodeULEB128AndInc(Ptr);
+ unsigned Opc = decodeULEB128AndIncUnsafe(++Ptr);
+ unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
MI.clear();
MI.setOpcode(Opc);
@@ -2366,8 +2366,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
}
case MCD::OPC_TryDecode: {
// Decode the Opcode value.
- unsigned Opc = decodeULEB128AndInc(++Ptr);
- unsigned DecodeIdx = decodeULEB128AndInc(Ptr);
+ unsigned Opc = decodeULEB128AndIncUnsafe(++Ptr);
+ unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
// NumToSkip is a plain 24-bit integer.
unsigned NumToSkip = *Ptr++;
NumToSkip |= (*Ptr++) << 8;
@@ -2399,8 +2399,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
}
case MCD::OPC_SoftFail: {
// Decode the mask values.
- uint64_t PositiveMask = decodeULEB128AndInc(++Ptr);
- uint64_t NegativeMask = decodeULEB128AndInc(Ptr);
+ uint64_t PositiveMask = decodeULEB128AndIncUnsafe(++Ptr);
+ uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
bool Fail = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
if (Fail)
S = MCDisassembler::SoftFail;
More information about the llvm-commits
mailing list