From 974c6f22aca3f13bdaecfa45f710b6627c64fdfd Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 24 May 2026 09:09:06 -0400 Subject: [PATCH] ClassUtils.toCleanName(String) resolves malformed array suffixes instead of throwing Called by ClassUtils.getClass(ClassLoader, String, boolean) --- .../org/apache/commons/lang3/ClassUtils.java | 7 +++++ .../apache/commons/lang3/ClassUtilsTest.java | 28 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/main/java/org/apache/commons/lang3/ClassUtils.java b/src/main/java/org/apache/commons/lang3/ClassUtils.java index 1e7a3b5e331..c0ce2a72633 100644 --- a/src/main/java/org/apache/commons/lang3/ClassUtils.java +++ b/src/main/java/org/apache/commons/lang3/ClassUtils.java @@ -1643,6 +1643,13 @@ private static String toCleanName(final String className) { throw new IllegalArgumentException(String.format("Class name greater than maxium length %,d", MAX_CLASS_NAME_LENGTH)); } if (canonicalName.endsWith(arrayMarker)) { + // Reject malformed inputs like "java.lang.String[]junk[]" or + // "java.lang.String[]][]" where the suffix is not composed of + // repeated "[]" pairs. + final String tail = canonicalName.substring(arrIdx); + if (!tail.matches("(?:\\[\\])+")) { + throw new IllegalArgumentException("Malformed array name: " + canonicalName); + } final int dims = (canonicalName.length() - arrIdx) / 2; if (dims > MAX_JVM_ARRAY_DIMENSION) { throw new IllegalArgumentException("Array dimension greater than JVM specification maximum of 255."); diff --git a/src/test/java/org/apache/commons/lang3/ClassUtilsTest.java b/src/test/java/org/apache/commons/lang3/ClassUtilsTest.java index 200e814e586..8f18a2bc881 100644 --- a/src/test/java/org/apache/commons/lang3/ClassUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/ClassUtilsTest.java @@ -1320,6 +1320,34 @@ void testGetClassRawPrimitives() throws ClassNotFoundException { assertEquals(void.class, ClassUtils.getClass("void")); } + /** + * Pre-patch: getClass("java.lang.String[]junk[]") silently returns String[][][][] (4 dims, because (24 - 16)/2 = 4 — junk is 4 chars). Post-patch: must + * throw IllegalArgumentException. + */ + @Test + public void testGetClassStringMalformedMiddleJunkRejected() { + assertThrows(IllegalArgumentException.class, () -> ClassUtils.getClass("java.lang.String[]junk[]")); + } + + /** + * Mutation control: suffix ends with "[]" so the array-branch is entered, and the suffix from arrIdx contains only '[' and ']' chars but NOT as well-formed + * pairs ("[]][]"). A char-class-only patch would accept this; the correct pair-validating patch must reject. Without this case, a weaker patch would still + * pass. + */ + @Test + public void testGetClassStringMalformedUnpairedBracketsRejected() { + assertThrows(IllegalArgumentException.class, () -> ClassUtils.getClass("java.lang.String[]][]")); + } + + /** + * Negative control: well-formed multi-dim array still resolves. Confirms the fix is minimal and does not over-reject. + */ + @Test + public void testGetClassStringWellFormedArrayStillResolves() throws Exception { + assertNotNull(ClassUtils.getClass("java.lang.String[]")); + assertNotNull(ClassUtils.getClass("java.lang.String[][]")); + } + @Test void testGetClassWithArrayClasses() throws Exception { assertGetClassReturnsClass(String[].class);