From 2184cc3d901b3ca3aa95f45b3788d5f048243a4b Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 2 Sep 2022 09:39:52 -0400 Subject: [PATCH] Fix argument validation in RuntimeType.InvokeMember The rollout of `!!` erroneously moved an ArgumentNullException to be thrown earlier in the method, preventing a null name from being used (which is valid with BindingFlags.CreateInstance). (Separately, we should consider fixing the nullable reference type annotation on `string name`, since null is allowed in some circumstances.) --- .../System.Private.CoreLib/src/System/RuntimeType.cs | 6 +++--- .../System.Reflection/tests/DefaultBinderTests.cs | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs index 81d6f994da54f..d4b45f21bc9d7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs @@ -459,8 +459,6 @@ public override bool IsAssignableFrom([NotNullWhen(true)] Type? c) string name, BindingFlags bindingFlags, Binder? binder, object? target, object?[]? providedArgs, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParams) { - ArgumentNullException.ThrowIfNull(name); - const BindingFlags MemberBindingMask = (BindingFlags)0x000000FF; const BindingFlags InvocationMask = (BindingFlags)0x0000FF00; const BindingFlags BinderGetSetField = BindingFlags.GetField | BindingFlags.SetField; @@ -567,10 +565,12 @@ public override bool IsAssignableFrom([NotNullWhen(true)] Type? c) // PutDispProperty and\or PutRefDispProperty ==> SetProperty. if ((bindingFlags & (BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty)) != 0) bindingFlags |= BindingFlags.SetProperty; + + ArgumentNullException.ThrowIfNull(name); if (name.Length == 0 || name.Equals("[DISPID=0]")) { // in InvokeMember we always pretend there is a default member if none is provided and we make it ToString - name = GetDefaultMemberName()! ?? "ToString"; + name = GetDefaultMemberName() ?? "ToString"; } // GetField or SetField diff --git a/src/libraries/System.Reflection/tests/DefaultBinderTests.cs b/src/libraries/System.Reflection/tests/DefaultBinderTests.cs index 99018fed4b6a1..874e1f3d5864c 100644 --- a/src/libraries/System.Reflection/tests/DefaultBinderTests.cs +++ b/src/libraries/System.Reflection/tests/DefaultBinderTests.cs @@ -167,6 +167,14 @@ public static void InvokeWithNamedParametersOutOfOrder() Assert.Equal(8, result); } + [Theory] + [InlineData("")] + [InlineData(null)] + public static void InvokeWithCreateInstance(string name) + { + Assert.IsType(typeof(Sample).InvokeMember(name, BindingFlags.CreateInstance, null, null, null)); + } + public class Test { public void TestMethod(int param1) { }