summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/source/Utility/DataExtractor.cpp37
-rw-r--r--lldb/unittests/Utility/DataExtractorTest.cpp45
2 files changed, 63 insertions, 19 deletions
diff --git a/lldb/source/Utility/DataExtractor.cpp b/lldb/source/Utility/DataExtractor.cpp
index 79a1f75d737..f642a8fc763 100644
--- a/lldb/source/Utility/DataExtractor.cpp
+++ b/lldb/source/Utility/DataExtractor.cpp
@@ -816,26 +816,25 @@ DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len,
// non-zero and there aren't enough available bytes, nullptr will be returned
// and "offset_ptr" will not be updated.
const char *DataExtractor::GetCStr(offset_t *offset_ptr) const {
- const char *cstr = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1));
- if (cstr) {
- const char *cstr_end = cstr;
- const char *end = reinterpret_cast<const char *>(m_end);
- while (cstr_end < end && *cstr_end)
- ++cstr_end;
-
- // Now we are either at the end of the data or we point to the
- // NULL C string terminator with cstr_end...
- if (*cstr_end == '\0') {
- // Advance the offset with one extra byte for the NULL terminator
- *offset_ptr += (cstr_end - cstr + 1);
- return cstr;
- }
+ const char *start = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1));
+ // Already at the end of the data.
+ if (!start)
+ return nullptr;
- // We reached the end of the data without finding a NULL C string
- // terminator. Fall through and return nullptr otherwise anyone that would
- // have used the result as a C string can wander into unknown memory...
- }
- return nullptr;
+ const char *end = reinterpret_cast<const char *>(m_end);
+
+ // Check all bytes for a null terminator that terminates a C string.
+ const char *terminator_or_end = std::find(start, end, '\0');
+
+ // We didn't find a null terminator, so return nullptr to indicate that there
+ // is no valid C string at that offset.
+ if (terminator_or_end == end)
+ return nullptr;
+
+ // Update offset_ptr for the caller to point to the data behind the
+ // terminator (which is 1 byte long).
+ *offset_ptr += (terminator_or_end - start + 1UL);
+ return start;
}
// Extracts a NULL terminated C string from the fixed length field of length
diff --git a/lldb/unittests/Utility/DataExtractorTest.cpp b/lldb/unittests/Utility/DataExtractorTest.cpp
index 1a974f26f32..fbf13399a1c 100644
--- a/lldb/unittests/Utility/DataExtractorTest.cpp
+++ b/lldb/unittests/Utility/DataExtractorTest.cpp
@@ -49,6 +49,51 @@ TEST(DataExtractorTest, PeekData) {
EXPECT_EQ(nullptr, E.PeekData(4, 1));
}
+TEST(DataExtractorTest, GetCStr) {
+ uint8_t buffer[] = {'X', 'f', 'o', 'o', '\0'};
+ DataExtractor E(buffer, sizeof buffer, lldb::eByteOrderLittle, 4);
+
+ lldb::offset_t offset = 1;
+ EXPECT_STREQ("foo", E.GetCStr(&offset));
+ EXPECT_EQ(5U, offset);
+}
+
+TEST(DataExtractorTest, GetCStrEmpty) {
+ uint8_t buffer[] = {'X', '\0'};
+ DataExtractor E(buffer, sizeof buffer, lldb::eByteOrderLittle, 4);
+
+ lldb::offset_t offset = 1;
+ EXPECT_STREQ("", E.GetCStr(&offset));
+ EXPECT_EQ(2U, offset);
+}
+
+TEST(DataExtractorTest, GetCStrUnterminated) {
+ uint8_t buffer[] = {'X', 'f', 'o', 'o'};
+ DataExtractor E(buffer, sizeof buffer, lldb::eByteOrderLittle, 4);
+
+ lldb::offset_t offset = 1;
+ EXPECT_EQ(nullptr, E.GetCStr(&offset));
+ EXPECT_EQ(1U, offset);
+}
+
+TEST(DataExtractorTest, GetCStrAtEnd) {
+ uint8_t buffer[] = {'X'};
+ DataExtractor E(buffer, sizeof buffer, lldb::eByteOrderLittle, 4);
+
+ lldb::offset_t offset = 1;
+ EXPECT_EQ(nullptr, E.GetCStr(&offset));
+ EXPECT_EQ(1U, offset);
+}
+
+TEST(DataExtractorTest, GetCStrAtNullOffset) {
+ uint8_t buffer[] = {'f', 'o', 'o', '\0'};
+ DataExtractor E(buffer, sizeof buffer, lldb::eByteOrderLittle, 4);
+
+ lldb::offset_t offset = 0;
+ EXPECT_STREQ("foo", E.GetCStr(&offset));
+ EXPECT_EQ(4U, offset);
+}
+
TEST(DataExtractorTest, GetMaxU64) {
uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
DataExtractor LE(buffer, sizeof(buffer), lldb::eByteOrderLittle,
OpenPOWER on IntegriCloud