Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 45d0444

Browse files
author
Koundinya Veluri
authored
Fix closed delegate deserialization to account for extension methods (#10901)
Functional fix for #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
1 parent cdb88f4 commit 45d0444

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

src/mscorlib/src/System/DelegateSerializationHolder.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -206,26 +206,34 @@ private Delegate GetDelegate(DelegateEntry de, int index)
206206

207207
// We cannot use Type.GetType directly, because of AppCompat - assembly names starting with '[' would fail to load.
208208
RuntimeType type = (RuntimeType)Assembly.GetType_Compat(de.assembly, de.type);
209-
RuntimeType targetType = (RuntimeType)Assembly.GetType_Compat(de.targetTypeAssembly, de.targetTypeName);
209+
210+
// {de.targetTypeAssembly, de.targetTypeName} do not actually refer to the type of the target, but the reflected
211+
// 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
212+
// inheritance chain, but those types may not be the same when the method is an extension method for the
213+
// target's type or a type in its inheritance chain.
210214

211215
// If we received the new style delegate encoding we already have the target MethodInfo in hand.
212216
if (m_methods != null)
213217
{
214-
if (de.target != null && !targetType.IsInstanceOfType(de.target))
215-
throw new InvalidCastException();
216-
Object target = de.target;
217-
d = Delegate.CreateDelegateNoSecurityCheck(type, target, m_methods[index]);
218+
// The method info is serialized, so the target type info is redundant. The desktop framework does no
219+
// additional verification on the target type info.
220+
d = Delegate.CreateDelegateNoSecurityCheck(type, de.target, m_methods[index]);
218221
}
219222
else
220223
{
221224
if (de.target != null)
222225
{
223-
if (!targetType.IsInstanceOfType(de.target))
224-
throw new InvalidCastException();
226+
// For consistency with the desktop framework, when the method info is not serialized for a closed
227+
// delegate, the method is assumed to be on the target's type or in its inheritance chain. An extension
228+
// method would not work on this path for the above reason and also because the delegate binds to
229+
// instance methods only. The desktop framework does no additional verification on the target type info.
225230
d = Delegate.CreateDelegate(type, de.target, de.methodName);
226231
}
227232
else
233+
{
234+
RuntimeType targetType = (RuntimeType)Assembly.GetType_Compat(de.targetTypeAssembly, de.targetTypeName);
228235
d = Delegate.CreateDelegate(type, targetType, de.methodName);
236+
}
229237
}
230238
}
231239
catch (Exception e)

0 commit comments

Comments
 (0)