[llvm] r357936 - llvm-undname: Fix more crashes and asserts on invalid inputs

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 8 12:46:53 PDT 2019


Author: nico
Date: Mon Apr  8 12:46:53 2019
New Revision: 357936

URL: http://llvm.org/viewvc/llvm-project?rev=357936&view=rev
Log:
llvm-undname: Fix more crashes and asserts on invalid inputs

For functions whose callers don't check that enough input is present,
add checks at the start of the function that enough input is there and
set Error otherwise.

For functions that return AST objects, return nullptr instead of
incomplete AST objects with nullptr fields if an error occurred during
the function.

Introduce a new function demangleDeclarator() for the sequence
demangleFullyQualifiedSymbolName(); demangleEncodedSymbol() and
use it in the two places that had this sequence. Let this new function
check that ConversionOperatorIdentifiers have a valid TargetType.

Some of the bad inputs found by oss-fuzz, others by inspection.

Differential Revision: https://reviews.llvm.org/D60354

Modified:
    llvm/trunk/include/llvm/Demangle/MicrosoftDemangle.h
    llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
    llvm/trunk/test/Demangle/invalid-manglings.test

Modified: llvm/trunk/include/llvm/Demangle/MicrosoftDemangle.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Demangle/MicrosoftDemangle.h?rev=357936&r1=357935&r2=357936&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Demangle/MicrosoftDemangle.h (original)
+++ llvm/trunk/include/llvm/Demangle/MicrosoftDemangle.h Mon Apr  8 12:46:53 2019
@@ -159,6 +159,7 @@ public:
 private:
   SymbolNode *demangleEncodedSymbol(StringView &MangledName,
                                     QualifiedNameNode *QN);
+  SymbolNode *demangleDeclarator(StringView &MangledName);
 
   VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
                                                StorageClass SC);

Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=357936&r1=357935&r2=357936&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Mon Apr  8 12:46:53 2019
@@ -65,7 +65,10 @@ static bool isMemberPointer(StringView M
   // 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 M
   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::demangleI
   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<VariableSymbolNode *>(Symbol);
@@ -400,7 +406,8 @@ FunctionSymbolNode *Demangler::demangleI
     }
 
     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::demangleFunctionIdentifierCod
 
 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::demangleEncodedSy
   if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
     ConversionOperatorIdentifierNode *COIN =
         static_cast<ConversionOperatorIdentifierNode *>(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<ConversionOperatorIdentifierNode *>(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
   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::demangleV
   VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop);
   VSN->SC = SC;
 
+  if (Error)
+    return nullptr;
+
   // <variable-type> ::= <type> <cvr-qualifiers>
   //                 ::= <type> <pointee-cvr-qualifiers> # pointers, references
   switch (VSN->Type->kind()) {
@@ -1574,6 +1600,11 @@ FuncClass Demangler::demangleFunctionCla
 }
 
 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::demangleVariable
 
 std::pair<Qualifiers, bool>
 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(String
       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(Stri
   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(Stri
     bool HasThisQuals = !(FC & (FC_Global | FC_Static));
     FSN = demangleFunctionType(MangledName, HasThisQuals);
   }
+
+  if (Error)
+    return nullptr;
+
   if (TTN) {
     *static_cast<FunctionSignatureNode *>(TTN) = *FSN;
     FSN = TTN;
@@ -1903,6 +1952,8 @@ PointerTypeNode *Demangler::demangleMemb
   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::demangleMemb
     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;

Modified: llvm/trunk/test/Demangle/invalid-manglings.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/invalid-manglings.test?rev=357936&r1=357935&r2=357936&view=diff
==============================================================================
--- llvm/trunk/test/Demangle/invalid-manglings.test (original)
+++ llvm/trunk/test/Demangle/invalid-manglings.test Mon Apr  8 12:46:53 2019
@@ -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 at 4
+; CHECK-EMPTY:
+; CHECK-NEXT: ??B at 4
+; CHECK-NEXT: error: Invalid mangled name
+
+?A?@?@???B at 4D
+; CHECK-EMPTY:
+; CHECK-NEXT: ?A?@?@???B at 4D
+; CHECK-NEXT: error: Invalid mangled name
+
+?A?@?@???B at 4DD
+; CHECK-EMPTY:
+; CHECK-NEXT: ?A?@?@???B at 4DD
+; CHECK-NEXT: error: Invalid mangled name
+
+??$A at P15@
+; CHECK-EMPTY:
+; CHECK-NEXT: ??$A at P15@
+; CHECK-NEXT: error: Invalid mangled name
+
+??$A at P
+; CHECK-EMPTY:
+; CHECK-NEXT: ??$A at 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




More information about the llvm-commits mailing list