From: Gary Gregory <garydgregory@gmail.com>
Date: Sat, 21 Sep 2024 17:23:08 -0400
Subject: [PATCH] Rewrite ClassUtils.getClass() without recursion to avoid
 StackOverflowError on very long inputs.

- This was found fuzz testing Apache Commons Text which relies on
ClassUtils.
- OssFuzz Issue 42522972:
apache-commons-text:StringSubstitutorInterpolatorFuzzer: Security
exception in org.apache.commons.lang3.ClassUtils.getClass

Reviewed-By: Daniel Leidert <dleidert@debian.org>
Origin: https://github.com/apache/commons-lang/commit/b424803abdb2bec818e4fbcb251ce031c22aca53
Bug: https://github.com/advisories/GHSA-j288-q9x7-2f5v
Bug-Debian: https://bugs.debian.org/1109126
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-48924
Bug-Freexian-Security: https://deb.freexian.com/extended-lts/tracker/CVE-2025-48924
---
 .../java/org/apache/commons/lang/ClassUtils.java   |  46 ++++++++++-----------
 .../apache/commons/lang/ClassUtilsOssFuzzTest.java | Bin 0 -> 17588 bytes
 2 files changed, 22 insertions(+), 24 deletions(-)
 create mode 100644 src/test/java/org/apache/commons/lang/ClassUtilsOssFuzzTest.java

diff --git a/src/main/java/org/apache/commons/lang/ClassUtils.java b/src/main/java/org/apache/commons/lang/ClassUtils.java
index 82665e2..3d463d9 100644
--- a/src/main/java/org/apache/commons/lang/ClassUtils.java
+++ b/src/main/java/org/apache/commons/lang/ClassUtils.java
@@ -748,30 +748,27 @@ public class ClassUtils {
      */
     public static Class getClass(
             ClassLoader classLoader, String className, boolean initialize) throws ClassNotFoundException {
-        try {
-            Class clazz;
-            if (abbreviationMap.containsKey(className)) {
-                String clsName = "[" + abbreviationMap.get(className);
-                clazz = Class.forName(clsName, initialize, classLoader).getComponentType();
-            } else {
-                clazz = Class.forName(toCanonicalName(className), initialize, classLoader);
-            }
-            return clazz;
-        } catch (ClassNotFoundException ex) {
-            // allow path separators (.) as inner class name separators
-            int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
-
-            if (lastDotIndex != -1) {
-                try {
-                    return getClass(classLoader, className.substring(0, lastDotIndex) +
-                            INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1),
-                            initialize);
-                } catch (ClassNotFoundException ex2) {
+        // This method was re-written to avoid recursion and stack overflows found by fuzz testing.
+        String next = className;
+        int lastDotIndex = -1;
+        do {
+            try {
+                Class clazz;
+                if (abbreviationMap.containsKey(className)) {
+                    String clsName = "[" + abbreviationMap.get(className);
+                    clazz = Class.forName(clsName, initialize, classLoader).getComponentType();
+                } else {
+                    clazz = Class.forName(toCanonicalName(className), initialize, classLoader);
+                }
+                return clazz;
+            } catch (final ClassNotFoundException ex) {
+                lastDotIndex = next.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
+                if (lastDotIndex != -1) {
+                    next = next.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR_CHAR + next.substring(lastDotIndex + 1);
                 }
             }
-
-            throw ex;
-        }
+        } while (lastDotIndex != -1);
+        throw new ClassNotFoundException(next);
     }
 
     /**
@@ -886,11 +883,12 @@ public class ClassUtils {
      */
     private static String toCanonicalName(String className) {
         className = StringUtils.deleteWhitespace(className);
+        final String arrayMarker = "[]";
         if (className == null) {
             throw new NullArgumentException("className");
-        } else if (className.endsWith("[]")) {
+        } else if (className.endsWith(arrayMarker)) {
             StrBuilder classNameBuffer = new StrBuilder();
-            while (className.endsWith("[]")) {
+            while (className.endsWith(arrayMarker)) {
                 className = className.substring(0, className.length() - 2);
                 classNameBuffer.append("[");
             }
diff --git a/src/test/java/org/apache/commons/lang/ClassUtilsOssFuzzTest.java b/src/test/java/org/apache/commons/lang/ClassUtilsOssFuzzTest.java
new file mode 100644
index 0000000..5ab7334
--- /dev/null
+++ b/src/test/java/org/apache/commons/lang/ClassUtilsOssFuzzTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.lang;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests {@link ClassUtils}.
+ */
+public class ClassUtilsOssFuzzTest extends TestCase {
+
+    public ClassUtilsOssFuzzTest(String name) {
+        super(name);
+    }
+
+    /**
+     * Tests that no StackOverflowError is thrown.
+     * <p>
+     * OSS-Fuzz Issue 42522972: apache-commons-text:StringSubstitutorInterpolatorFuzzer: Security exception in org.apache.commons.lang.ClassUtils.getClass
+     * </p>
+     */
+    public void testGetClassLongIllegalName() throws Exception {
+        // Input from Commons Text clusterfuzz-testcase-StringSubstitutorInterpolatorFuzzer-5447769450741760
+        assertGetClassThrowsClassNotFound(
+                "ˇda´~e]W]                   ~          t $t ${.u base64encoder{con+s {.u base64encoder{con+s          ~          t   ....................                                                                                      ................ˇˇˇˇˇˇˇˇˇˇ&${localhot:ˇˇˇˇˇˇ4ˇ.........  .........................s${.!. ${..  \\E],${conÅ       EEE]W€EÅE.! ${.u base64encoder{conÅ       EEE]W€EÅE.! ${.u base64encoder{con+s          ~          t   ....................................ˇˇˇˇˇˇˇˇˇˇ&${localhot:ˇˇˇˇˇˇ-636ˇ...............................................................     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - -......     t]V]W€EÅE.! $${.u - - }" );
+    }
+
+    /**
+     * Tests that no StackOverflowError is thrown.
+     */
+
+    public void testGetClassLongName() throws Exception {
+        assertGetClassThrowsClassNotFound( StringUtils.repeat("a.", 5_000) + "b" );
+    }
+
+    private void assertGetClassThrowsClassNotFound( String className ) throws Exception {
+        assertGetClassThrowsException( className, ClassNotFoundException.class );
+    }
+
+    private void assertGetClassThrowsException( String className, Class exceptionType ) throws Exception {
+        try {
+            ClassUtils.getClass( className );
+            fail( "ClassUtils.getClass() should fail with an exception of type " + exceptionType.getName() + " when given class name \"" + className + "\"." );
+        }
+        catch( Exception e ) {
+            assertTrue( exceptionType.isAssignableFrom( e.getClass() ) );
+        }
+    }
+}
