From cd63a636640c38d530aaa12476fc03ab7372f6a9 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Mon, 24 Jun 2019 09:11:24 +0000 Subject: [PATCH] [Support] Fix error handling in DataExtractor::get[US]LEB128 Summary: These functions are documented as not modifying the offset argument if the extraction fails (just like other DataExtractor functions). However, while reviewing D63591 we discovered that this is not the case -- if the function reaches the end of the data buffer, it will just return the value parsed until that point and set offset to point to the end of the buffer. This fixes the functions to act as advertised, and adds a regression test. Reviewers: dblaikie, probinson, bkramer Subscribers: kristina, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63645 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@364169 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/DataExtractor.cpp | 28 ++++++++++++------------- unittests/Support/DataExtractorTest.cpp | 10 +++++++++ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/Support/DataExtractor.cpp b/lib/Support/DataExtractor.cpp index 6328d779b3d..18e1423b546 100644 --- a/lib/Support/DataExtractor.cpp +++ b/lib/Support/DataExtractor.cpp @@ -157,12 +157,12 @@ uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const { byte = Data[offset++]; result |= uint64_t(byte & 0x7f) << shift; shift += 7; - if ((byte & 0x80) == 0) - break; + if ((byte & 0x80) == 0) { + *offset_ptr = offset; + return result; + } } - - *offset_ptr = offset; - return result; + return 0; } int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const { @@ -178,14 +178,14 @@ int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const { byte = Data[offset++]; result |= uint64_t(byte & 0x7f) << shift; shift += 7; - if ((byte & 0x80) == 0) - break; + if ((byte & 0x80) == 0) { + // Sign bit of byte is 2nd high order bit (0x40) + if (shift < 64 && (byte & 0x40)) + result |= -(1ULL << shift); + + *offset_ptr = offset; + return result; + } } - - // Sign bit of byte is 2nd high order bit (0x40) - if (shift < 64 && (byte & 0x40)) - result |= -(1ULL << shift); - - *offset_ptr = offset; - return result; + return 0; } diff --git a/unittests/Support/DataExtractorTest.cpp b/unittests/Support/DataExtractorTest.cpp index 5663dad5cb6..9726a74d81f 100644 --- a/unittests/Support/DataExtractorTest.cpp +++ b/unittests/Support/DataExtractorTest.cpp @@ -116,4 +116,14 @@ TEST(DataExtractorTest, LEB128) { EXPECT_EQ(8U, offset); } +TEST(DataExtractorTest, LEB128_error) { + DataExtractor DE(StringRef("\x81"), false, 8); + uint32_t Offset = 0; + EXPECT_EQ(0U, DE.getULEB128(&Offset)); + EXPECT_EQ(0U, Offset); + + Offset = 0; + EXPECT_EQ(0U, DE.getSLEB128(&Offset)); + EXPECT_EQ(0U, Offset); +} }