Skip to content

Commit efad149

Browse files
authored
[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: #90006
1 parent 6d89014 commit efad149

File tree

3 files changed

+42
-13
lines changed

3 files changed

+42
-13
lines changed

llvm/include/llvm/Support/LEB128.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,20 +200,26 @@ inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr,
200200
return Value;
201201
}
202202

203-
inline uint64_t decodeULEB128AndInc(const uint8_t *&p) {
203+
inline uint64_t decodeULEB128AndInc(const uint8_t *&p, const uint8_t *end,
204+
const char **error = nullptr) {
204205
unsigned n;
205-
auto ret = decodeULEB128(p, &n);
206+
auto ret = decodeULEB128(p, &n, end, error);
206207
p += n;
207208
return ret;
208209
}
209210

210-
inline int64_t decodeSLEB128AndInc(const uint8_t *&p) {
211+
inline int64_t decodeSLEB128AndInc(const uint8_t *&p, const uint8_t *end,
212+
const char **error = nullptr) {
211213
unsigned n;
212-
auto ret = decodeSLEB128(p, &n);
214+
auto ret = decodeSLEB128(p, &n, end, error);
213215
p += n;
214216
return ret;
215217
}
216218

219+
inline uint64_t decodeULEB128AndIncUnsafe(const uint8_t *&p) {
220+
return decodeULEB128AndInc(p, nullptr);
221+
}
222+
217223
/// Utility function to get the size of the ULEB128-encoded value.
218224
extern unsigned getULEB128Size(uint64_t Value);
219225

llvm/unittests/Support/LEB128Test.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ TEST(LEB128Test, DecodeInvalidULEB128) {
155155
EXPECT_NE(Error, nullptr); \
156156
EXPECT_EQ(0ul, Actual); \
157157
EXPECT_EQ(ERROR_OFFSET, ErrorOffset); \
158+
Value = reinterpret_cast<const uint8_t *>(VALUE); \
159+
Error = nullptr; \
160+
Actual = decodeULEB128AndInc(Value, Value + strlen(VALUE), &Error); \
161+
EXPECT_NE(Error, nullptr); \
162+
EXPECT_EQ(0ul, Actual); \
163+
EXPECT_EQ(ERROR_OFFSET, Value - reinterpret_cast<const uint8_t *>(VALUE)); \
158164
} while (0)
159165

160166
// Buffer overflow.
@@ -224,6 +230,12 @@ TEST(LEB128Test, DecodeInvalidSLEB128) {
224230
EXPECT_NE(Error, nullptr); \
225231
EXPECT_EQ(0ul, Actual); \
226232
EXPECT_EQ(ERROR_OFFSET, ErrorOffset); \
233+
Value = reinterpret_cast<const uint8_t *>(VALUE); \
234+
Error = nullptr; \
235+
Actual = decodeSLEB128AndInc(Value, Value + strlen(VALUE), &Error); \
236+
EXPECT_NE(Error, nullptr); \
237+
EXPECT_EQ(0ul, Actual); \
238+
EXPECT_EQ(ERROR_OFFSET, Value - reinterpret_cast<const uint8_t *>(VALUE)); \
227239
} while (0)
228240

229241
// Buffer overflow.
@@ -246,7 +258,7 @@ TEST(LEB128Test, DecodeAndInc) {
246258
#define EXPECT_LEB128(FUN, VALUE, SIZE) \
247259
do { \
248260
const uint8_t *V = reinterpret_cast<const uint8_t *>(VALUE), *P = V; \
249-
auto Expected = FUN(P), Actual = FUN##AndInc(P); \
261+
auto Expected = FUN(P), Actual = FUN##AndInc(P, P + strlen(VALUE)); \
250262
EXPECT_EQ(Actual, Expected); \
251263
EXPECT_EQ(P - V, SIZE); \
252264
} while (0)
@@ -255,6 +267,17 @@ TEST(LEB128Test, DecodeAndInc) {
255267
EXPECT_LEB128(decodeSLEB128, "\x7f", 1);
256268
EXPECT_LEB128(decodeSLEB128, "\x80\x01", 2);
257269
#undef EXPECT_LEB128
270+
271+
#define EXPECT_LEB128(FUN, VALUE, SIZE) \
272+
do { \
273+
const uint8_t *V = reinterpret_cast<const uint8_t *>(VALUE), *P = V; \
274+
auto Expected = FUN(P), Actual = FUN##AndIncUnsafe(P); \
275+
EXPECT_EQ(Actual, Expected); \
276+
EXPECT_EQ(P - V, SIZE); \
277+
} while (0)
278+
EXPECT_LEB128(decodeULEB128, "\x7f", 1);
279+
EXPECT_LEB128(decodeULEB128, "\x80\x01", 2);
280+
#undef EXPECT_LEB128
258281
}
259282

260283
TEST(LEB128Test, SLEB128Size) {

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,7 +2301,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23012301
}
23022302
case MCD::OPC_CheckField: {
23032303
// Decode the start value.
2304-
unsigned Start = decodeULEB128AndInc(++Ptr);
2304+
unsigned Start = decodeULEB128AndIncUnsafe(++Ptr);
23052305
unsigned Len = *Ptr;)";
23062306
if (IsVarLenInst)
23072307
OS << "\n makeUp(insn, Start + Len);";
@@ -2328,7 +2328,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23282328
}
23292329
case MCD::OPC_CheckPredicate: {
23302330
// Decode the Predicate Index value.
2331-
unsigned PIdx = decodeULEB128AndInc(++Ptr);
2331+
unsigned PIdx = decodeULEB128AndIncUnsafe(++Ptr);
23322332
// NumToSkip is a plain 24-bit integer.
23332333
unsigned NumToSkip = *Ptr++;
23342334
NumToSkip |= (*Ptr++) << 8;
@@ -2345,8 +2345,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23452345
}
23462346
case MCD::OPC_Decode: {
23472347
// Decode the Opcode value.
2348-
unsigned Opc = decodeULEB128AndInc(++Ptr);
2349-
unsigned DecodeIdx = decodeULEB128AndInc(Ptr);
2348+
unsigned Opc = decodeULEB128AndIncUnsafe(++Ptr);
2349+
unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
23502350
23512351
MI.clear();
23522352
MI.setOpcode(Opc);
@@ -2366,8 +2366,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23662366
}
23672367
case MCD::OPC_TryDecode: {
23682368
// Decode the Opcode value.
2369-
unsigned Opc = decodeULEB128AndInc(++Ptr);
2370-
unsigned DecodeIdx = decodeULEB128AndInc(Ptr);
2369+
unsigned Opc = decodeULEB128AndIncUnsafe(++Ptr);
2370+
unsigned DecodeIdx = decodeULEB128AndIncUnsafe(Ptr);
23712371
// NumToSkip is a plain 24-bit integer.
23722372
unsigned NumToSkip = *Ptr++;
23732373
NumToSkip |= (*Ptr++) << 8;
@@ -2399,8 +2399,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23992399
}
24002400
case MCD::OPC_SoftFail: {
24012401
// Decode the mask values.
2402-
uint64_t PositiveMask = decodeULEB128AndInc(++Ptr);
2403-
uint64_t NegativeMask = decodeULEB128AndInc(Ptr);
2402+
uint64_t PositiveMask = decodeULEB128AndIncUnsafe(++Ptr);
2403+
uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
24042404
bool Fail = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
24052405
if (Fail)
24062406
S = MCDisassembler::SoftFail;

0 commit comments

Comments
 (0)