From e31d9c6227049cd63551ac7e8f3c4c4290312111 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 23 Aug 2022 15:12:44 -0400 Subject: [PATCH] Context: https://github.com/xamarin/xamarin-android/pull/7285#discussion_r951760448 (#1029) `Java.Inteorp.JniEnvironment.Types.RegisterNatives()` is overloaded: namespace Java.Interop { partial class JniEnvironment { partial class Types { public static void RegisterNatives (JniObjectReference type, JniNativeMethodRegistration[] methods); public static void RegisterNatives (JniObjectReference type, JniNativeMethodRegistration[] methods, int numMethods); } } } If the `int numMethods` overload is used, then: 1. it should be possible to pass an array which contains *more* than `numMethods` elements, and 2. Passing such an array shouldn't throw an exception. For example: var methods = new JniNativeMethodRegistration [10]; JniEnvironment.Types.RegisterNatives (type, methods, 0); Instead, when using a Debug configuration build of `Java.Interop.dll`, a `NullReferenceException` would be thrown, because the `foreach` loop would traverse *every element*, not just the first `numMethods` elements, which could result in accessing `methods[i].Marshaler.GetType()`, which could be `null`. Fix the `DEBUG && NETCOREAPP` check so that only the first `numMethods` elements are accessed, *not* all of them, and add a `null` check around `JniNativeMethodRegistration.Marshaler` access. This prevents the `NullReferenceException`. Additionally, add some parameter validation and throw an `ArgumentOutOfRangeException` if `numMethods` is negative or is greater than `methods.Length`. --- src/Java.Interop/Java.Interop/JniEnvironment.Types.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Java.Interop/Java.Interop/JniEnvironment.Types.cs b/src/Java.Interop/Java.Interop/JniEnvironment.Types.cs index af0ca4ff1..a50f0b19a 100644 --- a/src/Java.Interop/Java.Interop/JniEnvironment.Types.cs +++ b/src/Java.Interop/Java.Interop/JniEnvironment.Types.cs @@ -200,9 +200,15 @@ public static void RegisterNatives (JniObjectReference type, JniNativeMethodRegi public static void RegisterNatives (JniObjectReference type, JniNativeMethodRegistration [] methods, int numMethods) { + if ((numMethods < 0) || + (numMethods > (methods?.Length ?? 0))) { + throw new ArgumentOutOfRangeException (nameof (numMethods), numMethods, + $"`numMethods` must be between 0 and `methods.Length` ({methods?.Length ?? 0})!"); + } #if DEBUG && NETCOREAPP - foreach (var m in methods) { - if (m.Marshaler.GetType ().GenericTypeArguments.Length != 0) { + for (int i = 0; methods != null && i < numMethods; ++i) { + var m = methods [i]; + if (m.Marshaler != null && m.Marshaler.GetType ().GenericTypeArguments.Length != 0) { var method = m.Marshaler.Method; Debug.WriteLine ($"JNIEnv::RegisterNatives() given a generic delegate type `{m.Marshaler.GetType()}`. .NET Core doesn't like this."); Debug.WriteLine ($" Java: {m.Name}{m.Signature}");