[lldb] Fix logic error in AppleObjCTypeEncodingParser (#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.
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
using namespace lldb_private;
|
||||
@@ -41,13 +42,17 @@ std::string AppleObjCTypeEncodingParser::ReadStructName(StringLexer &type) {
|
||||
return std::string(buffer.GetString());
|
||||
}
|
||||
|
||||
std::string AppleObjCTypeEncodingParser::ReadQuotedString(StringLexer &type) {
|
||||
std::optional<std::string>
|
||||
AppleObjCTypeEncodingParser::ReadQuotedString(StringLexer &type) {
|
||||
if (!type.HasAtLeast(1))
|
||||
return std::nullopt;
|
||||
|
||||
StreamString buffer;
|
||||
while (type.HasAtLeast(1) && type.Peek() != '"')
|
||||
while (type.Peek() != '"') {
|
||||
buffer.Printf("%c", type.Next());
|
||||
StringLexer::Character next = type.Next();
|
||||
UNUSED_IF_ASSERT_DISABLED(next);
|
||||
assert(next == '"');
|
||||
if (!type.HasAtLeast(1))
|
||||
return std::nullopt;
|
||||
}
|
||||
return std::string(buffer.GetString());
|
||||
}
|
||||
|
||||
@@ -70,10 +75,12 @@ AppleObjCTypeEncodingParser::ReadStructElement(TypeSystemClang &ast_ctx,
|
||||
StringLexer &type,
|
||||
bool for_expression) {
|
||||
StructElement retval;
|
||||
if (type.NextIf('"'))
|
||||
retval.name = ReadQuotedString(type);
|
||||
if (!type.NextIf('"'))
|
||||
return retval;
|
||||
if (type.NextIf('"')) {
|
||||
if (auto maybe_name = ReadQuotedString(type))
|
||||
retval.name = *maybe_name;
|
||||
else
|
||||
return retval;
|
||||
}
|
||||
uint32_t bitfield_size = 0;
|
||||
retval.type = BuildType(ast_ctx, type, for_expression, &bitfield_size);
|
||||
retval.bitfield = bitfield_size;
|
||||
@@ -198,7 +205,10 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
|
||||
// quoted string is a class name. - If we see anything else, the quoted
|
||||
// string is a field name and we push it back onto type.
|
||||
|
||||
name = ReadQuotedString(type);
|
||||
if (auto maybe_name = ReadQuotedString(type))
|
||||
name = *maybe_name;
|
||||
else
|
||||
return clang::QualType();
|
||||
|
||||
if (type.HasAtLeast(1)) {
|
||||
switch (type.Peek()) {
|
||||
|
||||
@@ -63,7 +63,7 @@ private:
|
||||
|
||||
uint32_t ReadNumber(StringLexer &type);
|
||||
|
||||
std::string ReadQuotedString(StringLexer &type);
|
||||
std::optional<std::string> ReadQuotedString(StringLexer &type);
|
||||
|
||||
ObjCLanguageRuntime &m_runtime;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user