Index: llvm/include/llvm/Demangle/MicrosoftDemangle.h =================================================================== --- llvm/include/llvm/Demangle/MicrosoftDemangle.h +++ llvm/include/llvm/Demangle/MicrosoftDemangle.h @@ -159,6 +159,7 @@ private: SymbolNode *demangleEncodedSymbol(StringView &MangledName, QualifiedNameNode *QN); + SymbolNode *demangleDeclarator(StringView &MangledName); VariableSymbolNode *demangleVariableEncoding(StringView &MangledName, StorageClass SC); Index: llvm/lib/Demangle/MicrosoftDemangle.cpp =================================================================== --- llvm/lib/Demangle/MicrosoftDemangle.cpp +++ llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -65,7 +65,10 @@ // 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 @@ 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 @@ 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 @@ } 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 @@ 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,35 @@ 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 (Symbol) { + 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 +758,7 @@ 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 +785,9 @@ VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop); VSN->SC = SC; + if (Error) + return nullptr; + // ::= // ::= # pointers, references switch (VSN->Type->kind()) { @@ -1574,6 +1599,11 @@ } CallingConv Demangler::demangleCallingConvention(StringView &MangledName) { + if (MangledName.empty()) { + Error = true; + return CallingConv::None; + } + switch (MangledName.popFront()) { case 'A': case 'B': @@ -1624,6 +1654,10 @@ 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 +1696,11 @@ std::tie(Quals, IsMember) = demangleQualifiers(MangledName); } + if (MangledName.empty()) { + Error = true; + return nullptr; + } + TypeNode *Ty = nullptr; if (isTagType(MangledName)) Ty = demangleClassType(MangledName); @@ -1736,6 +1775,11 @@ if (MangledName.consumeFront("$$J0")) ExtraFlags = FC_ExternC; + if (MangledName.empty()) { + Error = true; + return nullptr; + } + FuncClass FC = demangleFunctionClass(MangledName); FC = FuncClass(ExtraFlags | FC); @@ -1763,6 +1807,10 @@ 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 +1951,8 @@ Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); + // Safe because this is only called if isMemberPointer() returns true, which + // guarantess there's at least one more character after the qualifiers. if (MangledName.consumeFront("8")) { Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); Pointer->Pointee = demangleFunctionType(MangledName, true); @@ -1910,11 +1960,12 @@ 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; Index: llvm/test/Demangle/invalid-manglings.test =================================================================== --- llvm/test/Demangle/invalid-manglings.test +++ llvm/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