Skip to content

Commit 7a276c8

Browse files
authored
[lldb] Fix logic error in AppleObjCTypeEncodingParser (llvm#137067)
Fixes parsing of an ObjC type encoding such as `{?="a""b"}`. Parsing of such a type encoding would lead to an assert. This was observed when running `language objc class-table dump`. The function `ReadQuotedString` consumes the closing quote, however one of its two callers (`ReadStructElement`) was also consuming a quote. For the above type encoding, where two quoted strings occur back to back, the parser would unintentionally consume the opening quote of the second quoted string - leaving the remaining text with an unbalanced quote. This changes fixes `ReadStructElement` to not consume a quote after calling `ReadQuotedString`. For callers to know whether a string was successfully parsed, `ReadQuotedString` now returns an optional string.
1 parent 2de936b commit 7a276c8

File tree

2 files changed

+21
-11
lines changed

2 files changed

+21
-11
lines changed

lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "clang/Basic/TargetInfo.h"
2121

22+
#include <optional>
2223
#include <vector>
2324

2425
using namespace lldb_private;
@@ -41,13 +42,17 @@ std::string AppleObjCTypeEncodingParser::ReadStructName(StringLexer &type) {
4142
return std::string(buffer.GetString());
4243
}
4344

44-
std::string AppleObjCTypeEncodingParser::ReadQuotedString(StringLexer &type) {
45+
std::optional<std::string>
46+
AppleObjCTypeEncodingParser::ReadQuotedString(StringLexer &type) {
47+
if (!type.HasAtLeast(1))
48+
return std::nullopt;
49+
4550
StreamString buffer;
46-
while (type.HasAtLeast(1) && type.Peek() != '"')
51+
while (type.Peek() != '"') {
4752
buffer.Printf("%c", type.Next());
48-
StringLexer::Character next = type.Next();
49-
UNUSED_IF_ASSERT_DISABLED(next);
50-
assert(next == '"');
53+
if (!type.HasAtLeast(1))
54+
return std::nullopt;
55+
}
5156
return std::string(buffer.GetString());
5257
}
5358

@@ -70,10 +75,12 @@ AppleObjCTypeEncodingParser::ReadStructElement(TypeSystemClang &ast_ctx,
7075
StringLexer &type,
7176
bool for_expression) {
7277
StructElement retval;
73-
if (type.NextIf('"'))
74-
retval.name = ReadQuotedString(type);
75-
if (!type.NextIf('"'))
76-
return retval;
78+
if (type.NextIf('"')) {
79+
if (auto maybe_name = ReadQuotedString(type))
80+
retval.name = *maybe_name;
81+
else
82+
return retval;
83+
}
7784
uint32_t bitfield_size = 0;
7885
retval.type = BuildType(ast_ctx, type, for_expression, &bitfield_size);
7986
retval.bitfield = bitfield_size;
@@ -198,7 +205,10 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
198205
// quoted string is a class name. - If we see anything else, the quoted
199206
// string is a field name and we push it back onto type.
200207

201-
name = ReadQuotedString(type);
208+
if (auto maybe_name = ReadQuotedString(type))
209+
name = *maybe_name;
210+
else
211+
return clang::QualType();
202212

203213
if (type.HasAtLeast(1)) {
204214
switch (type.Peek()) {

lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class AppleObjCTypeEncodingParser : public ObjCLanguageRuntime::EncodingToType {
6363

6464
uint32_t ReadNumber(StringLexer &type);
6565

66-
std::string ReadQuotedString(StringLexer &type);
66+
std::optional<std::string> ReadQuotedString(StringLexer &type);
6767

6868
ObjCLanguageRuntime &m_runtime;
6969
};

0 commit comments

Comments
 (0)