diff --git a/include/llvm/Demangle/MicrosoftDemangle.h b/include/llvm/Demangle/MicrosoftDemangle.h index a23e3273509..66553b4b250 100644 --- a/include/llvm/Demangle/MicrosoftDemangle.h +++ b/include/llvm/Demangle/MicrosoftDemangle.h @@ -159,6 +159,7 @@ public: private: SymbolNode *demangleEncodedSymbol(StringView &MangledName, QualifiedNameNode *QN); + SymbolNode *demangleDeclarator(StringView &MangledName); VariableSymbolNode *demangleVariableEncoding(StringView &MangledName, StorageClass SC); diff --git a/lib/Demangle/MicrosoftDemangle.cpp b/lib/Demangle/MicrosoftDemangle.cpp index 0704f7bac51..b0f4d9a8a8f 100644 --- a/lib/Demangle/MicrosoftDemangle.cpp +++ b/lib/Demangle/MicrosoftDemangle.cpp @@ -65,7 +65,10 @@ static bool isMemberPointer(StringView MangledName, bool &Error) { // If it starts with a number, then 6 indicates a non-member function // pointer, and 8 indicates a member function pointer. if (startsWithDigit(MangledName)) { - assert(MangledName[0] == '6' || MangledName[0] == '8'); + if (MangledName[0] != '6' && MangledName[0] != '8') { + Error = true; + return false; + } return (MangledName[0] == '8'); } @@ -75,7 +78,10 @@ static bool isMemberPointer(StringView MangledName, bool &Error) { MangledName.consumeFront('I'); // restrict MangledName.consumeFront('F'); // unaligned - assert(!MangledName.empty()); + if (MangledName.empty()) { + Error = true; + return false; + } // The next value should be either ABCD (non-member) or QRST (member). switch (MangledName.front()) { @@ -378,11 +384,11 @@ FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName, if (MangledName.consumeFront('?')) IsKnownStaticDataMember = true; - QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); + SymbolNode *Symbol = demangleDeclarator(MangledName); + if (Error) + return nullptr; - SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN); FunctionSymbolNode *FSN = nullptr; - Symbol->Name = QN; if (Symbol->kind() == NodeKind::VariableSymbol) { DSIN->Variable = static_cast(Symbol); @@ -400,7 +406,8 @@ FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName, } FSN = demangleFunctionEncoding(MangledName); - FSN->Name = synthesizeQualifiedName(Arena, DSIN); + if (FSN) + FSN->Name = synthesizeQualifiedName(Arena, DSIN); } else { if (IsKnownStaticDataMember) { // This was supposed to be a static data member, but we got a function. @@ -674,6 +681,11 @@ Demangler::demangleFunctionIdentifierCode(StringView &MangledName, SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName, QualifiedNameNode *Name) { + if (MangledName.empty()) { + Error = true; + return nullptr; + } + // Read a variable. switch (MangledName.front()) { case '0': @@ -693,11 +705,36 @@ SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName, if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) { ConversionOperatorIdentifierNode *COIN = static_cast(UQN); - COIN->TargetType = FSN->Signature->ReturnType; + if (FSN) + COIN->TargetType = FSN->Signature->ReturnType; } return FSN; } +SymbolNode *Demangler::demangleDeclarator(StringView &MangledName) { + // What follows is a main symbol name. This may include namespaces or class + // back references. + QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); + if (Error) + return nullptr; + + SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN); + if (Error) + return nullptr; + Symbol->Name = QN; + + IdentifierNode *UQN = QN->getUnqualifiedIdentifier(); + if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) { + ConversionOperatorIdentifierNode *COIN = + static_cast(UQN); + if (!COIN->TargetType) { + Error = true; + return nullptr; + } + } + return Symbol; +} + // Parser entry point. SymbolNode *Demangler::parse(StringView &MangledName) { // We can't demangle MD5 names, just output them as-is. @@ -722,21 +759,7 @@ SymbolNode *Demangler::parse(StringView &MangledName) { if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName)) return SI; - // What follows is a main symbol name. This may include namespaces or class - // back references. - QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); - if (Error) - return nullptr; - - SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN); - if (Symbol) { - Symbol->Name = QN; - } - - if (Error) - return nullptr; - - return Symbol; + return demangleDeclarator(MangledName); } TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) { @@ -763,6 +786,9 @@ VariableSymbolNode *Demangler::demangleVariableEncoding(StringView &MangledName, VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop); VSN->SC = SC; + if (Error) + return nullptr; + // ::= // ::= # pointers, references switch (VSN->Type->kind()) { @@ -1574,6 +1600,11 @@ FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { } CallingConv Demangler::demangleCallingConvention(StringView &MangledName) { + if (MangledName.empty()) { + Error = true; + return CallingConv::None; + } + switch (MangledName.popFront()) { case 'A': case 'B': @@ -1624,6 +1655,10 @@ StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) { std::pair Demangler::demangleQualifiers(StringView &MangledName) { + if (MangledName.empty()) { + Error = true; + return std::make_pair(Q_None, false); + } switch (MangledName.popFront()) { // Member qualifiers @@ -1662,6 +1697,11 @@ TypeNode *Demangler::demangleType(StringView &MangledName, std::tie(Quals, IsMember) = demangleQualifiers(MangledName); } + if (MangledName.empty()) { + Error = true; + return nullptr; + } + TypeNode *Ty = nullptr; if (isTagType(MangledName)) Ty = demangleClassType(MangledName); @@ -1736,6 +1776,11 @@ Demangler::demangleFunctionEncoding(StringView &MangledName) { if (MangledName.consumeFront("$$J0")) ExtraFlags = FC_ExternC; + if (MangledName.empty()) { + Error = true; + return nullptr; + } + FuncClass FC = demangleFunctionClass(MangledName); FC = FuncClass(ExtraFlags | FC); @@ -1763,6 +1808,10 @@ Demangler::demangleFunctionEncoding(StringView &MangledName) { bool HasThisQuals = !(FC & (FC_Global | FC_Static)); FSN = demangleFunctionType(MangledName, HasThisQuals); } + + if (Error) + return nullptr; + if (TTN) { *static_cast(TTN) = *FSN; FSN = TTN; @@ -1903,6 +1952,8 @@ PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) { Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); + // isMemberPointer() only returns true if there is at least one character + // after the qualifiers. if (MangledName.consumeFront("8")) { Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); Pointer->Pointee = demangleFunctionType(MangledName, true); @@ -1910,11 +1961,12 @@ PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) { Qualifiers PointeeQuals = Q_None; bool IsMember = false; std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName); - assert(IsMember); + assert(IsMember || Error); Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop); - Pointer->Pointee->Quals = PointeeQuals; + if (Pointer->Pointee) + Pointer->Pointee->Quals = PointeeQuals; } return Pointer; diff --git a/test/Demangle/invalid-manglings.test b/test/Demangle/invalid-manglings.test index 7a7d8ee0734..b6021761ed2 100644 --- a/test/Demangle/invalid-manglings.test +++ b/test/Demangle/invalid-manglings.test @@ -29,3 +29,63 @@ ; CHECK-EMPTY: ; CHECK-NEXT: ? @@ YC@ ; CHECK-NEXT: error: Invalid mangled name + +??B@$$J0 +; CHECK-EMPTY: +; CHECK-NEXT: ??B@$$J0 +; CHECK-NEXT: error: Invalid mangled name + +??B@4 +; CHECK-EMPTY: +; CHECK-NEXT: ??B@4 +; CHECK-NEXT: error: Invalid mangled name + +?A?@?@???B@4D +; CHECK-EMPTY: +; CHECK-NEXT: ?A?@?@???B@4D +; CHECK-NEXT: error: Invalid mangled name + +?A?@?@???B@4DD +; CHECK-EMPTY: +; CHECK-NEXT: ?A?@?@???B@4DD +; CHECK-NEXT: error: Invalid mangled name + +??$A@P15@ +; CHECK-EMPTY: +; CHECK-NEXT: ??$A@P15@ +; CHECK-NEXT: error: Invalid mangled name + +??$A@P +; CHECK-EMPTY: +; CHECK-NEXT: ??$A@P +; CHECK-NEXT: error: Invalid mangled name + +?A@@ +; CHECK-EMPTY: +; CHECK-NEXT: ?A@@ +; CHECK-NEXT: error: Invalid mangled name + +?A@@P +; CHECK-EMPTY: +; CHECK-NEXT: ?A@@P +; CHECK-NEXT: error: Invalid mangled name + +?A@@4PQA@@ +; CHECK-EMPTY: +; CHECK-NEXT: ?A@@4PQA@@ +; CHECK-NEXT: error: Invalid mangled name + +??__E +; CHECK-EMPTY: +; CHECK-NEXT: ??__E +; CHECK-NEXT: error: Invalid mangled name + +??__E@@ +; CHECK-EMPTY: +; CHECK-NEXT: ??__E@@ +; CHECK-NEXT: error: Invalid mangled name + +??__E?Foo@@0HA@@ +; CHECK-EMPTY: +; CHECK-NEXT: ??__E?Foo@@0HA@@ +; CHECK-NEXT: error: Invalid mangled name