From 29eeb65a1682d572b83503ff418fae1ebfc39b07 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Fri, 9 Oct 2026 00:26:00 +0200 Subject: [PATCH 1/2] [Mono.Android] Guard JNI string lengths `Android.Runtime.JNIEnv.NewString()` forwards its length to JNI without a bounds check. Reject negative and oversized lengths before pinning while preserving the existing null-first return behavior. Context: https://github.com/dotnet/android/issues/11467 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/Mono.Android/Android.Runtime/JNIEnv.cs | 11 ++++++++--- .../Mono.Android-Tests/Java.Interop/JnienvTest.cs | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Mono.Android/Android.Runtime/JNIEnv.cs b/src/Mono.Android/Android.Runtime/JNIEnv.cs index 8064341be10..eab57f9e4cd 100644 --- a/src/Mono.Android/Android.Runtime/JNIEnv.cs +++ b/src/Mono.Android/Android.Runtime/JNIEnv.cs @@ -484,13 +484,18 @@ public static unsafe IntPtr NewString (string? text) return JniEnvironment.Strings.NewString (text).Handle; } - public static unsafe IntPtr NewString (char[]? text, int length) + public static IntPtr NewString (char[]? text, int length) { if (text == null) return IntPtr.Zero; - fixed (char *s = text) - return JniEnvironment.Strings.NewString (s, length).Handle; + if (length < 0 || length > text.Length) + throw new ArgumentOutOfRangeException (nameof (length)); + + unsafe { + fixed (char *s = text) + return JniEnvironment.Strings.NewString (s, length).Handle; + } } static void AssertCompatibleArrayTypes (Type srcElementType, IntPtr destArray) diff --git a/tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/JnienvTest.cs b/tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/JnienvTest.cs index 99b91a57412..bb72dc37860 100644 --- a/tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/JnienvTest.cs +++ b/tests/Mono.Android-Tests/Mono.Android-Tests/Java.Interop/JnienvTest.cs @@ -21,6 +21,20 @@ namespace Java.InteropTests [TestFixture] public class JnienvTest { + [Test] + [Category ("JniStringLength")] + public void NewStringValidatesLengthAndSupportsPrefix () + { + var text = new[] { 'f', 'o', 'o' }; + + Assert.Throws (() => JNIEnv.NewString (text, -1)); + Assert.Throws (() => JNIEnv.NewString (text, text.Length + 1)); + Assert.AreEqual (IntPtr.Zero, JNIEnv.NewString ((char[]?) null, -1)); + + IntPtr handle = JNIEnv.NewString (text, 2); + Assert.AreEqual ("fo", JNIEnv.GetString (handle, JniHandleOwnership.TransferLocalRef)); + } + [Test] public void TestMyPaintColor () { From d897f2258863fa589c514d1db6616dafc8127e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Rozs=C3=ADval?= Date: Fri, 9 Oct 2026 09:52:50 +0200 Subject: [PATCH 2/2] Add check for zero length in JNIEnv.cs Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/Mono.Android/Android.Runtime/JNIEnv.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Mono.Android/Android.Runtime/JNIEnv.cs b/src/Mono.Android/Android.Runtime/JNIEnv.cs index eab57f9e4cd..74dc2846d4f 100644 --- a/src/Mono.Android/Android.Runtime/JNIEnv.cs +++ b/src/Mono.Android/Android.Runtime/JNIEnv.cs @@ -491,6 +491,8 @@ public static IntPtr NewString (char[]? text, int length) if (length < 0 || length > text.Length) throw new ArgumentOutOfRangeException (nameof (length)); + if (length == 0) + return JniEnvironment.Strings.NewString ("").Handle; unsafe { fixed (char *s = text)