Skip to content

Commit 7fe2bef

Browse files
committed
Demangler: handle errors in demangleType
Makes sure that invalid runtime type strings result in errors and not fail silently. In worst case this could lead to wrong reconstructed metatypes which can result in all kind of memory corruption. relates to rdar://129861211
1 parent 9580b21 commit 7fe2bef

File tree

4 files changed

+38
-22
lines changed

4 files changed

+38
-22
lines changed

include/swift/RemoteInspection/TypeRefBuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,8 @@ class TypeRefBuilder {
638638
auto substitutedDemangleTree = Builder.demangleTypeRef(
639639
substitutedTypeRef,
640640
/* useOpaqueTypeSymbolicReferences */ true);
641+
if (!substitutedDemangleTree)
642+
continue;
641643

642644
// If the substituted type is an opaque type, also gather info
643645
// about which protocols it is required to conform to and the

lib/Demangling/Demangler.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ llvm::StringRef swift::Demangle::dropSwiftManglingPrefix(StringRef mangledName){
224224
}
225225

226226
static bool isAliasNode(Demangle::NodePointer Node) {
227+
if (!Node)
228+
return false;
227229
switch (Node->getKind()) {
228230
case Demangle::Node::Kind::Type:
229231
return isAliasNode(Node->getChild(0));
@@ -241,6 +243,8 @@ bool swift::Demangle::isAlias(llvm::StringRef mangledName) {
241243
}
242244

243245
static bool isClassNode(Demangle::NodePointer Node) {
246+
if (!Node)
247+
return false;
244248
switch (Node->getKind()) {
245249
case Demangle::Node::Kind::Type:
246250
return isClassNode(Node->getChild(0));
@@ -259,6 +263,8 @@ bool swift::Demangle::isClass(llvm::StringRef mangledName) {
259263
}
260264

261265
static bool isEnumNode(Demangle::NodePointer Node) {
266+
if (!Node)
267+
return false;
262268
switch (Node->getKind()) {
263269
case Demangle::Node::Kind::Type:
264270
return isEnumNode(Node->getChild(0));
@@ -277,6 +283,8 @@ bool swift::Demangle::isEnum(llvm::StringRef mangledName) {
277283
}
278284

279285
static bool isProtocolNode(Demangle::NodePointer Node) {
286+
if (!Node)
287+
return false;
280288
switch (Node->getKind()) {
281289
case Demangle::Node::Kind::Type:
282290
return isProtocolNode(Node->getChild(0));
@@ -296,6 +304,8 @@ bool swift::Demangle::isProtocol(llvm::StringRef mangledName) {
296304
}
297305

298306
static bool isStructNode(Demangle::NodePointer Node) {
307+
if (!Node)
308+
return false;
299309
switch (Node->getKind()) {
300310
case Demangle::Node::Kind::Type:
301311
return isStructNode(Node->getChild(0));
@@ -774,12 +784,16 @@ NodePointer Demangler::demangleType(StringRef MangledName,
774784
std::function<SymbolicReferenceResolver_t> Resolver) {
775785
DemangleInitRAII state(*this, MangledName, std::move(Resolver));
776786

777-
parseAndPushNodes();
787+
if (!parseAndPushNodes())
788+
return nullptr;
789+
790+
NodePointer Result = popNode();
778791

779-
if (NodePointer Result = popNode())
780-
return Result;
792+
// The result is only valid if it was the only node on the stack.
793+
if (popNode())
794+
return nullptr;
781795

782-
return createNode(Node::Kind::Suffix, Text);
796+
return Result;
783797
}
784798

785799
bool Demangler::parseAndPushNodes() {

test/Runtime/demangleToMetadata.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,28 +79,28 @@ DemangleToMetadataTests.test("function types") {
7979
expectEqual(type(of: f0_throws), _typeByName("yyKc")!)
8080

8181
// More parameters.
82-
expectEqual(type(of: f1), _typeByName("yyyt_tc")!)
83-
expectEqual(type(of: f2), _typeByName("yyyt_yttc")!)
82+
expectEqual(type(of: f1), _typeByName("yyt_tc")!)
83+
expectEqual(type(of: f2), _typeByName("yyt_yttc")!)
8484

8585
// Variadic parameters.
86-
expectEqual(type(of: f1_variadic), _typeByName("yyytd_tc")!)
86+
expectEqual(type(of: f1_variadic), _typeByName("yytd_tc")!)
8787

8888
// Inout parameters.
89-
expectEqual(type(of: f1_inout), _typeByName("yyytzc")!)
89+
expectEqual(type(of: f1_inout), _typeByName("yytzc")!)
9090

9191
// Ownership parameters.
92-
expectEqual(type(of: f1_shared), _typeByName("yyyXlhc")!)
93-
expectEqual(type(of: f1_owned), _typeByName("yyyXlnc")!)
92+
expectEqual(type(of: f1_shared), _typeByName("yyXlhc")!)
93+
expectEqual(type(of: f1_owned), _typeByName("yyXlnc")!)
9494

9595
// Concurrent function types.
96-
expectEqual(type(of: f1_takes_concurrent), _typeByName("yyyyYbXEc")!)
96+
expectEqual(type(of: f1_takes_concurrent), _typeByName("yyyYbXEc")!)
9797

9898
// Mix-and-match.
99-
expectEqual(type(of: f2_variadic_inout), _typeByName("yyytd_ytztc")!)
99+
expectEqual(type(of: f2_variadic_inout), _typeByName("yytd_ytztc")!)
100100

101101
// A function type that hasn't been built before.
102102
expectEqual("(Int, Float, Double, String, Character, UInt, Bool) -> ()",
103-
String(describing: _typeByName("yySi_SfSdSSs9CharacterVSuSbtc")!))
103+
String(describing: _typeByName("ySi_SfSdSSs9CharacterVSuSbtc")!))
104104

105105
// Escaping
106106
expectEqual(type(of: f1_escaping), _typeByName("ySfSicc")!)
@@ -145,16 +145,16 @@ func f1_composition_superclass(_: C & P1 & P2) { }
145145

146146
DemangleToMetadataTests.test("existential types") {
147147
// Any, AnyObject
148-
expectEqual(type(of: f2_any_anyobject), _typeByName("yyyp_yXltc")!)
148+
expectEqual(type(of: f2_any_anyobject), _typeByName("yyp_yXltc")!)
149149

150150
// References to protocols.
151-
expectEqual(type(of: f1_composition), _typeByName("yy4main2P1_4main2P2pc")!)
151+
expectEqual(type(of: f1_composition), _typeByName("y4main2P1_4main2P2pc")!)
152152

153153
// Reference to protocol with AnyObject.
154-
expectEqual(type(of: f1_composition_anyobject), _typeByName("yy4main2P1_Xlc")!)
154+
expectEqual(type(of: f1_composition_anyobject), _typeByName("y4main2P1_Xlc")!)
155155

156156
// References to superclass.
157-
expectEqual(type(of: f1_composition_superclass), _typeByName("yy4main2P1_4main2P2AA1CCXcc")!)
157+
expectEqual(type(of: f1_composition_superclass), _typeByName("y4main2P1_4main2P2AA1CCXcc")!)
158158

159159
// Demangle an existential type that hasn't been seen before.
160160
expectEqual("P1 & P2 & P3", String(describing: _typeByName("4main2P1_4main2P24main2P3p")!))

test/Runtime/demangleToMetadataObjC.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ func f1_composition_objc_protocol_P4(_: mainP4) { }
4040

4141
DemangleToMetadataTests.test("@objc protocols") {
4242
expectEqual(type(of: f1_composition_objc_protocol),
43-
_typeByName("yy4main2P1_pc")!)
43+
_typeByName("y4main2P1_pc")!)
4444
expectEqual(type(of: f1_composition_objc_protocol_P4),
45-
_typeByName("yy4main0A2P4_pc")!)
45+
_typeByName("y4main0A2P4_pc")!)
4646
}
4747

4848
DemangleToMetadataTests.test("Objective-C classes") {
@@ -53,13 +53,13 @@ func f1_composition_NSCoding(_: NSCoding) { }
5353
func f1_composition_P5(_: P5) { }
5454

5555
DemangleToMetadataTests.test("Objective-C protocols") {
56-
expectEqual(type(of: f1_composition_NSCoding), _typeByName("yySo8NSCoding_pc")!)
56+
expectEqual(type(of: f1_composition_NSCoding), _typeByName("ySo8NSCoding_pc")!)
5757

5858
// @objc Swift protocols can be found by their Objective-C names...
59-
expectEqual(type(of: f1_composition_P5), _typeByName("yySo15P5RenamedInObjC_pc")!)
59+
expectEqual(type(of: f1_composition_P5), _typeByName("ySo15P5RenamedInObjC_pc")!)
6060

6161
// ... but not their Swift names.
62-
expectNil(_typeByName("yy4main2P5_pc"))
62+
expectNil(_typeByName("y4main2P5_pc"))
6363
}
6464

6565
DemangleToMetadataTests.test("Classes that don't exist") {

0 commit comments

Comments
 (0)