mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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
This commit is contained in:
@@ -638,6 +638,8 @@ public:
|
||||
auto substitutedDemangleTree = Builder.demangleTypeRef(
|
||||
substitutedTypeRef,
|
||||
/* useOpaqueTypeSymbolicReferences */ true);
|
||||
if (!substitutedDemangleTree)
|
||||
continue;
|
||||
|
||||
// If the substituted type is an opaque type, also gather info
|
||||
// about which protocols it is required to conform to and the
|
||||
|
||||
@@ -224,6 +224,8 @@ llvm::StringRef swift::Demangle::dropSwiftManglingPrefix(StringRef mangledName){
|
||||
}
|
||||
|
||||
static bool isAliasNode(Demangle::NodePointer Node) {
|
||||
if (!Node)
|
||||
return false;
|
||||
switch (Node->getKind()) {
|
||||
case Demangle::Node::Kind::Type:
|
||||
return isAliasNode(Node->getChild(0));
|
||||
@@ -241,6 +243,8 @@ bool swift::Demangle::isAlias(llvm::StringRef mangledName) {
|
||||
}
|
||||
|
||||
static bool isClassNode(Demangle::NodePointer Node) {
|
||||
if (!Node)
|
||||
return false;
|
||||
switch (Node->getKind()) {
|
||||
case Demangle::Node::Kind::Type:
|
||||
return isClassNode(Node->getChild(0));
|
||||
@@ -259,6 +263,8 @@ bool swift::Demangle::isClass(llvm::StringRef mangledName) {
|
||||
}
|
||||
|
||||
static bool isEnumNode(Demangle::NodePointer Node) {
|
||||
if (!Node)
|
||||
return false;
|
||||
switch (Node->getKind()) {
|
||||
case Demangle::Node::Kind::Type:
|
||||
return isEnumNode(Node->getChild(0));
|
||||
@@ -277,6 +283,8 @@ bool swift::Demangle::isEnum(llvm::StringRef mangledName) {
|
||||
}
|
||||
|
||||
static bool isProtocolNode(Demangle::NodePointer Node) {
|
||||
if (!Node)
|
||||
return false;
|
||||
switch (Node->getKind()) {
|
||||
case Demangle::Node::Kind::Type:
|
||||
return isProtocolNode(Node->getChild(0));
|
||||
@@ -296,6 +304,8 @@ bool swift::Demangle::isProtocol(llvm::StringRef mangledName) {
|
||||
}
|
||||
|
||||
static bool isStructNode(Demangle::NodePointer Node) {
|
||||
if (!Node)
|
||||
return false;
|
||||
switch (Node->getKind()) {
|
||||
case Demangle::Node::Kind::Type:
|
||||
return isStructNode(Node->getChild(0));
|
||||
@@ -774,12 +784,16 @@ NodePointer Demangler::demangleType(StringRef MangledName,
|
||||
std::function<SymbolicReferenceResolver_t> Resolver) {
|
||||
DemangleInitRAII state(*this, MangledName, std::move(Resolver));
|
||||
|
||||
parseAndPushNodes();
|
||||
if (!parseAndPushNodes())
|
||||
return nullptr;
|
||||
|
||||
if (NodePointer Result = popNode())
|
||||
return Result;
|
||||
NodePointer Result = popNode();
|
||||
|
||||
return createNode(Node::Kind::Suffix, Text);
|
||||
// The result is only valid if it was the only node on the stack.
|
||||
if (popNode())
|
||||
return nullptr;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Demangler::parseAndPushNodes() {
|
||||
|
||||
@@ -79,28 +79,28 @@ DemangleToMetadataTests.test("function types") {
|
||||
expectEqual(type(of: f0_throws), _typeByName("yyKc")!)
|
||||
|
||||
// More parameters.
|
||||
expectEqual(type(of: f1), _typeByName("yyyt_tc")!)
|
||||
expectEqual(type(of: f2), _typeByName("yyyt_yttc")!)
|
||||
expectEqual(type(of: f1), _typeByName("yyt_tc")!)
|
||||
expectEqual(type(of: f2), _typeByName("yyt_yttc")!)
|
||||
|
||||
// Variadic parameters.
|
||||
expectEqual(type(of: f1_variadic), _typeByName("yyytd_tc")!)
|
||||
expectEqual(type(of: f1_variadic), _typeByName("yytd_tc")!)
|
||||
|
||||
// Inout parameters.
|
||||
expectEqual(type(of: f1_inout), _typeByName("yyytzc")!)
|
||||
expectEqual(type(of: f1_inout), _typeByName("yytzc")!)
|
||||
|
||||
// Ownership parameters.
|
||||
expectEqual(type(of: f1_shared), _typeByName("yyyXlhc")!)
|
||||
expectEqual(type(of: f1_owned), _typeByName("yyyXlnc")!)
|
||||
expectEqual(type(of: f1_shared), _typeByName("yyXlhc")!)
|
||||
expectEqual(type(of: f1_owned), _typeByName("yyXlnc")!)
|
||||
|
||||
// Concurrent function types.
|
||||
expectEqual(type(of: f1_takes_concurrent), _typeByName("yyyyYbXEc")!)
|
||||
expectEqual(type(of: f1_takes_concurrent), _typeByName("yyyYbXEc")!)
|
||||
|
||||
// Mix-and-match.
|
||||
expectEqual(type(of: f2_variadic_inout), _typeByName("yyytd_ytztc")!)
|
||||
expectEqual(type(of: f2_variadic_inout), _typeByName("yytd_ytztc")!)
|
||||
|
||||
// A function type that hasn't been built before.
|
||||
expectEqual("(Int, Float, Double, String, Character, UInt, Bool) -> ()",
|
||||
String(describing: _typeByName("yySi_SfSdSSs9CharacterVSuSbtc")!))
|
||||
String(describing: _typeByName("ySi_SfSdSSs9CharacterVSuSbtc")!))
|
||||
|
||||
// Escaping
|
||||
expectEqual(type(of: f1_escaping), _typeByName("ySfSicc")!)
|
||||
@@ -145,16 +145,16 @@ func f1_composition_superclass(_: C & P1 & P2) { }
|
||||
|
||||
DemangleToMetadataTests.test("existential types") {
|
||||
// Any, AnyObject
|
||||
expectEqual(type(of: f2_any_anyobject), _typeByName("yyyp_yXltc")!)
|
||||
expectEqual(type(of: f2_any_anyobject), _typeByName("yyp_yXltc")!)
|
||||
|
||||
// References to protocols.
|
||||
expectEqual(type(of: f1_composition), _typeByName("yy4main2P1_4main2P2pc")!)
|
||||
expectEqual(type(of: f1_composition), _typeByName("y4main2P1_4main2P2pc")!)
|
||||
|
||||
// Reference to protocol with AnyObject.
|
||||
expectEqual(type(of: f1_composition_anyobject), _typeByName("yy4main2P1_Xlc")!)
|
||||
expectEqual(type(of: f1_composition_anyobject), _typeByName("y4main2P1_Xlc")!)
|
||||
|
||||
// References to superclass.
|
||||
expectEqual(type(of: f1_composition_superclass), _typeByName("yy4main2P1_4main2P2AA1CCXcc")!)
|
||||
expectEqual(type(of: f1_composition_superclass), _typeByName("y4main2P1_4main2P2AA1CCXcc")!)
|
||||
|
||||
// Demangle an existential type that hasn't been seen before.
|
||||
expectEqual("P1 & P2 & P3", String(describing: _typeByName("4main2P1_4main2P24main2P3p")!))
|
||||
|
||||
@@ -40,9 +40,9 @@ func f1_composition_objc_protocol_P4(_: mainP4) { }
|
||||
|
||||
DemangleToMetadataTests.test("@objc protocols") {
|
||||
expectEqual(type(of: f1_composition_objc_protocol),
|
||||
_typeByName("yy4main2P1_pc")!)
|
||||
_typeByName("y4main2P1_pc")!)
|
||||
expectEqual(type(of: f1_composition_objc_protocol_P4),
|
||||
_typeByName("yy4main0A2P4_pc")!)
|
||||
_typeByName("y4main0A2P4_pc")!)
|
||||
}
|
||||
|
||||
DemangleToMetadataTests.test("Objective-C classes") {
|
||||
@@ -53,13 +53,13 @@ func f1_composition_NSCoding(_: NSCoding) { }
|
||||
func f1_composition_P5(_: P5) { }
|
||||
|
||||
DemangleToMetadataTests.test("Objective-C protocols") {
|
||||
expectEqual(type(of: f1_composition_NSCoding), _typeByName("yySo8NSCoding_pc")!)
|
||||
expectEqual(type(of: f1_composition_NSCoding), _typeByName("ySo8NSCoding_pc")!)
|
||||
|
||||
// @objc Swift protocols can be found by their Objective-C names...
|
||||
expectEqual(type(of: f1_composition_P5), _typeByName("yySo15P5RenamedInObjC_pc")!)
|
||||
expectEqual(type(of: f1_composition_P5), _typeByName("ySo15P5RenamedInObjC_pc")!)
|
||||
|
||||
// ... but not their Swift names.
|
||||
expectNil(_typeByName("yy4main2P5_pc"))
|
||||
expectNil(_typeByName("y4main2P5_pc"))
|
||||
}
|
||||
|
||||
DemangleToMetadataTests.test("Classes that don't exist") {
|
||||
|
||||
Reference in New Issue
Block a user