From: Koundinya Veluri Date: Wed, 12 Apr 2017 17:33:52 +0000 (-0700) Subject: Fix closed delegate deserialization to account for extension methods (dotnet/coreclr... X-Git-Tag: submit/tizen/20210909.063632~11030^2~7289 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=433b212506fb425f4d25c23a4060bcc312ea5b8f;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Fix closed delegate deserialization to account for extension methods (dotnet/coreclr#10901) Functional fix for dotnet/coreclr#9597: - The code was incorrectly assuming that the serialized target type info refers to the target object's type; it actually refers to the method's reflected type, which may not be the same type when it's an extension method Commit migrated from https://github.com/dotnet/coreclr/commit/45d0444a05f0bbceb2f259ce483c080f0991be1b --- diff --git a/src/coreclr/src/mscorlib/src/System/DelegateSerializationHolder.cs b/src/coreclr/src/mscorlib/src/System/DelegateSerializationHolder.cs index 5f8f0ef..d7ad827 100644 --- a/src/coreclr/src/mscorlib/src/System/DelegateSerializationHolder.cs +++ b/src/coreclr/src/mscorlib/src/System/DelegateSerializationHolder.cs @@ -206,26 +206,34 @@ namespace System // We cannot use Type.GetType directly, because of AppCompat - assembly names starting with '[' would fail to load. RuntimeType type = (RuntimeType)Assembly.GetType_Compat(de.assembly, de.type); - RuntimeType targetType = (RuntimeType)Assembly.GetType_Compat(de.targetTypeAssembly, de.targetTypeName); + + // {de.targetTypeAssembly, de.targetTypeName} do not actually refer to the type of the target, but the reflected + // type of the method. Those types may be the same when the method is on the target's type or on a type in its + // inheritance chain, but those types may not be the same when the method is an extension method for the + // target's type or a type in its inheritance chain. // If we received the new style delegate encoding we already have the target MethodInfo in hand. if (m_methods != null) { - if (de.target != null && !targetType.IsInstanceOfType(de.target)) - throw new InvalidCastException(); - Object target = de.target; - d = Delegate.CreateDelegateNoSecurityCheck(type, target, m_methods[index]); + // The method info is serialized, so the target type info is redundant. The desktop framework does no + // additional verification on the target type info. + d = Delegate.CreateDelegateNoSecurityCheck(type, de.target, m_methods[index]); } else { if (de.target != null) { - if (!targetType.IsInstanceOfType(de.target)) - throw new InvalidCastException(); + // For consistency with the desktop framework, when the method info is not serialized for a closed + // delegate, the method is assumed to be on the target's type or in its inheritance chain. An extension + // method would not work on this path for the above reason and also because the delegate binds to + // instance methods only. The desktop framework does no additional verification on the target type info. d = Delegate.CreateDelegate(type, de.target, de.methodName); } else + { + RuntimeType targetType = (RuntimeType)Assembly.GetType_Compat(de.targetTypeAssembly, de.targetTypeName); d = Delegate.CreateDelegate(type, targetType, de.methodName); + } } } catch (Exception e)