llvm.org GIT mirror llvm / 5388309
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357936 91177308-0d34-0410-b5e6-96231b3b80d8 Nico Weber 1 year, 7 months ago
3 changed file(s) with 138 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
158158 private:
159159 SymbolNode *demangleEncodedSymbol(StringView &MangledName,
160160 QualifiedNameNode *QN);
161 SymbolNode *demangleDeclarator(StringView &MangledName);
161162
162163 VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
163164 StorageClass SC);
6464 // If it starts with a number, then 6 indicates a non-member function
6565 // pointer, and 8 indicates a member function pointer.
6666 if (startsWithDigit(MangledName)) {
67 assert(MangledName[0] == '6' || MangledName[0] == '8');
67 if (MangledName[0] != '6' && MangledName[0] != '8') {
68 Error = true;
69 return false;
70 }
6871 return (MangledName[0] == '8');
6972 }
7073
7477 MangledName.consumeFront('I'); // restrict
7578 MangledName.consumeFront('F'); // unaligned
7679
77 assert(!MangledName.empty());
80 if (MangledName.empty()) {
81 Error = true;
82 return false;
83 }
7884
7985 // The next value should be either ABCD (non-member) or QRST (member).
8086 switch (MangledName.front()) {
377383 if (MangledName.consumeFront('?'))
378384 IsKnownStaticDataMember = true;
379385
380 QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
381
382 SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
386 SymbolNode *Symbol = demangleDeclarator(MangledName);
387 if (Error)
388 return nullptr;
389
383390 FunctionSymbolNode *FSN = nullptr;
384 Symbol->Name = QN;
385391
386392 if (Symbol->kind() == NodeKind::VariableSymbol) {
387393 DSIN->Variable = static_cast(Symbol);
399405 }
400406
401407 FSN = demangleFunctionEncoding(MangledName);
402 FSN->Name = synthesizeQualifiedName(Arena, DSIN);
408 if (FSN)
409 FSN->Name = synthesizeQualifiedName(Arena, DSIN);
403410 } else {
404411 if (IsKnownStaticDataMember) {
405412 // This was supposed to be a static data member, but we got a function.
673680
674681 SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName,
675682 QualifiedNameNode *Name) {
683 if (MangledName.empty()) {
684 Error = true;
685 return nullptr;
686 }
687
676688 // Read a variable.
677689 switch (MangledName.front()) {
678690 case '0':
692704 if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
693705 ConversionOperatorIdentifierNode *COIN =
694706 static_cast(UQN);
695 COIN->TargetType = FSN->Signature->ReturnType;
707 if (FSN)
708 COIN->TargetType = FSN->Signature->ReturnType;
696709 }
697710 return FSN;
711 }
712
713 SymbolNode *Demangler::demangleDeclarator(StringView &MangledName) {
714 // What follows is a main symbol name. This may include namespaces or class
715 // back references.
716 QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
717 if (Error)
718 return nullptr;
719
720 SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
721 if (Error)
722 return nullptr;
723 Symbol->Name = QN;
724
725 IdentifierNode *UQN = QN->getUnqualifiedIdentifier();
726 if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
727 ConversionOperatorIdentifierNode *COIN =
728 static_cast(UQN);
729 if (!COIN->TargetType) {
730 Error = true;
731 return nullptr;
732 }
733 }
734 return Symbol;
698735 }
699736
700737 // Parser entry point.
721758 if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName))
722759 return SI;
723760
724 // What follows is a main symbol name. This may include namespaces or class
725 // back references.
726 QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
727 if (Error)
728 return nullptr;
729
730 SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
731 if (Symbol) {
732 Symbol->Name = QN;
733 }
734
735 if (Error)
736 return nullptr;
737
738 return Symbol;
761 return demangleDeclarator(MangledName);
739762 }
740763
741764 TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) {
761784
762785 VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop);
763786 VSN->SC = SC;
787
788 if (Error)
789 return nullptr;
764790
765791 // ::=
766792 // ::= # pointers, references
15731599 }
15741600
15751601 CallingConv Demangler::demangleCallingConvention(StringView &MangledName) {
1602 if (MangledName.empty()) {
1603 Error = true;
1604 return CallingConv::None;
1605 }
1606
15761607 switch (MangledName.popFront()) {
15771608 case 'A':
15781609 case 'B':
16231654
16241655 std::pair
16251656 Demangler::demangleQualifiers(StringView &MangledName) {
1657 if (MangledName.empty()) {
1658 Error = true;
1659 return std::make_pair(Q_None, false);
1660 }
16261661
16271662 switch (MangledName.popFront()) {
16281663 // Member qualifiers
16611696 std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
16621697 }
16631698
1699 if (MangledName.empty()) {
1700 Error = true;
1701 return nullptr;
1702 }
1703
16641704 TypeNode *Ty = nullptr;
16651705 if (isTagType(MangledName))
16661706 Ty = demangleClassType(MangledName);
17351775 if (MangledName.consumeFront("$$J0"))
17361776 ExtraFlags = FC_ExternC;
17371777
1778 if (MangledName.empty()) {
1779 Error = true;
1780 return nullptr;
1781 }
1782
17381783 FuncClass FC = demangleFunctionClass(MangledName);
17391784 FC = FuncClass(ExtraFlags | FC);
17401785
17621807 bool HasThisQuals = !(FC & (FC_Global | FC_Static));
17631808 FSN = demangleFunctionType(MangledName, HasThisQuals);
17641809 }
1810
1811 if (Error)
1812 return nullptr;
1813
17651814 if (TTN) {
17661815 *static_cast(TTN) = *FSN;
17671816 FSN = TTN;
19021951 Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
19031952 Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
19041953
1954 // isMemberPointer() only returns true if there is at least one character
1955 // after the qualifiers.
19051956 if (MangledName.consumeFront("8")) {
19061957 Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
19071958 Pointer->Pointee = demangleFunctionType(MangledName, true);
19091960 Qualifiers PointeeQuals = Q_None;
19101961 bool IsMember = false;
19111962 std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName);
1912 assert(IsMember);
1963 assert(IsMember || Error);
19131964 Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
19141965
19151966 Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop);
1916 Pointer->Pointee->Quals = PointeeQuals;
1967 if (Pointer->Pointee)
1968 Pointer->Pointee->Quals = PointeeQuals;
19171969 }
19181970
19191971 return Pointer;
2828 ; CHECK-EMPTY:
2929 ; CHECK-NEXT: ? @@ YC@
3030 ; CHECK-NEXT: error: Invalid mangled name
31
32 ??B@$$J0
33 ; CHECK-EMPTY:
34 ; CHECK-NEXT: ??B@$$J0
35 ; CHECK-NEXT: error: Invalid mangled name
36
37 ??B@4
38 ; CHECK-EMPTY:
39 ; CHECK-NEXT: ??B@4
40 ; CHECK-NEXT: error: Invalid mangled name
41
42 ?A?@?@???B@4D
43 ; CHECK-EMPTY:
44 ; CHECK-NEXT: ?A?@?@???B@4D
45 ; CHECK-NEXT: error: Invalid mangled name
46
47 ?A?@?@???B@4DD
48 ; CHECK-EMPTY:
49 ; CHECK-NEXT: ?A?@?@???B@4DD
50 ; CHECK-NEXT: error: Invalid mangled name
51
52 ??$A@P15@
53 ; CHECK-EMPTY:
54 ; CHECK-NEXT: ??$A@P15@
55 ; CHECK-NEXT: error: Invalid mangled name
56
57 ??$A@P
58 ; CHECK-EMPTY:
59 ; CHECK-NEXT: ??$A@P
60 ; CHECK-NEXT: error: Invalid mangled name
61
62 ?A@@
63 ; CHECK-EMPTY:
64 ; CHECK-NEXT: ?A@@
65 ; CHECK-NEXT: error: Invalid mangled name
66
67 ?A@@P
68 ; CHECK-EMPTY:
69 ; CHECK-NEXT: ?A@@P
70 ; CHECK-NEXT: error: Invalid mangled name
71
72 ?A@@4PQA@@
73 ; CHECK-EMPTY:
74 ; CHECK-NEXT: ?A@@4PQA@@
75 ; CHECK-NEXT: error: Invalid mangled name
76
77 ??__E
78 ; CHECK-EMPTY:
79 ; CHECK-NEXT: ??__E
80 ; CHECK-NEXT: error: Invalid mangled name
81
82 ??__E@@
83 ; CHECK-EMPTY:
84 ; CHECK-NEXT: ??__E@@
85 ; CHECK-NEXT: error: Invalid mangled name
86
87 ??__E?Foo@@0HA@@
88 ; CHECK-EMPTY:
89 ; CHECK-NEXT: ??__E?Foo@@0HA@@
90 ; CHECK-NEXT: error: Invalid mangled name