From db930214adc4f543a7b66026214684ed3aa8fd15 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 30 Jun 2022 12:24:08 -0400 Subject: [PATCH] [Java.Interop] JniTypeSignature & CultureInfo, empty strings Fixes: https://github.com/xamarin/java.interop/issues/335 Context: 920ea6482f7252412d626c4a2ecff0df6de6d428 Commit 920ea648 optimized `JniTypeManager.AssertSimpleReference()` by using `string.IndexOf(char)`. This dovetails with Issue #335, which wanted to optimize `JniTypeSignature` by removing calls to `string.Contains(string)`. Fix #335, and update the `JniTypeSignature` constructor to use `string.IndexOf(char)` instead of `string.Contains(string)`, and use string indexers instead of `string.StartsWith()` and `string.EndsWith()`. `Java.Interop.dll` has no remaining usage of `string.StartsWith()` and `string.EndsWith()`. Additionally, update `JniTypeSignature` so that the empty string `""` is *not* treated as a valid type signature. This is arguably a breaking change, but the empty string never made sense, *and* would throw an `IndexOutOfRangeException` with `JniTypeManager.Parse()`. --- src/Java.Interop/Java.Interop/JniTypeSignature.cs | 10 +++++++--- .../Java.Interop/JniTypeSignatureTest.cs | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Java.Interop/Java.Interop/JniTypeSignature.cs b/src/Java.Interop/Java.Interop/JniTypeSignature.cs index e7edb7b07..f409061a4 100644 --- a/src/Java.Interop/Java.Interop/JniTypeSignature.cs +++ b/src/Java.Interop/Java.Interop/JniTypeSignature.cs @@ -43,11 +43,13 @@ public string Name { public JniTypeSignature (string? simpleReference, int arrayRank = 0, bool keyword = false) { if (simpleReference != null) { - if (simpleReference.IndexOf (".", StringComparison.Ordinal) >= 0) + if (simpleReference.Length < 1) + throw new ArgumentException ("The empty string is not a valid JNI simple reference.", nameof (simpleReference)); + if (simpleReference.IndexOf ('.') >= 0) throw new ArgumentException ("JNI type names do not contain '.', they use '/'. Are you sure you're using a JNI type name?", nameof (simpleReference)); - if (simpleReference.StartsWith ("[", StringComparison.Ordinal)) + if (simpleReference [0] == '[') throw new ArgumentException ("To specify an array, use the ArrayRank property.", nameof (simpleReference)); - if (simpleReference.StartsWith ("L", StringComparison.Ordinal) && simpleReference.EndsWith (";", StringComparison.Ordinal)) + if (simpleReference [0] == 'L' && simpleReference [simpleReference.Length-1] == ';' ) throw new ArgumentException ("JNI type references are not supported.", nameof (simpleReference)); } @@ -105,6 +107,8 @@ public static bool TryParse (string signature, [NotNullWhen (true)] out JniTypeS if (signature == null) return new ArgumentNullException (nameof (signature)); + if (signature.Length < 1) + return new ArgumentException ("The empty string is not a valid JNI simple reference.", nameof (signature)); int i = 0; int r = 0; diff --git a/tests/Java.Interop-Tests/Java.Interop/JniTypeSignatureTest.cs b/tests/Java.Interop-Tests/Java.Interop/JniTypeSignatureTest.cs index 4f197111e..32cc66698 100644 --- a/tests/Java.Interop-Tests/Java.Interop/JniTypeSignatureTest.cs +++ b/tests/Java.Interop-Tests/Java.Interop/JniTypeSignatureTest.cs @@ -15,6 +15,14 @@ public void Constructor_Exceptions () Assert.Throws (() => new JniTypeSignature ("java.lang.Object")); Assert.Throws (() => new JniTypeSignature ("[[I")); Assert.Throws (() => new JniTypeSignature ("Ljava/lang/Object;")); + Assert.Throws (() => new JniTypeSignature ("")); + } + + [Test] + public void DefaultConstructor () + { + var t = new JniTypeSignature (); + Assert.False (t.IsValid); } [Test] @@ -55,6 +63,7 @@ public void QualifiedReference () public void Parse () { Assert.Throws (() => JniTypeSignature.Parse ((string) null)); + Assert.Throws (() => JniTypeSignature.Parse ("")); Assert.Throws (() => JniTypeSignature.Parse ("java.lang.String")); Assert.Throws (() => JniTypeSignature.Parse ("Ljava/lang/String;I")); Assert.Throws (() => JniTypeSignature.Parse ("ILjava/lang/String;")); @@ -78,6 +87,12 @@ static void AssertGetJniTypeInfoForJniTypeReference (string jniTypeReference, st Assert.AreEqual (jniTypeName, sig.SimpleReference, "JniTypeName for: " + jniTypeReference); Assert.AreEqual (arrayRank, sig.ArrayRank, "ArrayRank for: " + jniTypeReference); } + + [Test] + public void TryParse () + { + Assert.False (JniTypeSignature.TryParse ("", out var _)); + } } }