This is an automated email from the ASF dual-hosted git repository.

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git


The following commit(s) were added to refs/heads/master by this push:
     new 5dede14ab reject varargs candidates with too few arguments in 
MemberUtils (#1828)
5dede14ab is described below

commit 5dede14ab1e385b6d972b8bcb4f1f0f941e59db2
Author: alhuda <[email protected]>
AuthorDate: Tue Oct 20 02:00:08 2026 +0530

    reject varargs candidates with too few arguments in MemberUtils (#1828)
    
    isMatchingExecutable accepted a varargs method or constructor without
    checking that enough arguments were supplied for its fixed parameters,
    so getMatchingAccessibleMethod and getMatchingAccessibleConstructor
    returned inapplicable members and invokeMethod, invokeStaticMethod and
    invokeConstructor failed with ArrayIndexOutOfBoundsException from
    toVarArgs instead of NoSuchMethodException.
---
 .../java/org/apache/commons/lang3/reflect/MemberUtils.java  |  2 +-
 .../apache/commons/lang3/reflect/ConstructorUtilsTest.java  | 13 +++++++++++++
 .../org/apache/commons/lang3/reflect/MethodUtilsTest.java   |  6 ++++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/commons/lang3/reflect/MemberUtils.java 
b/src/main/java/org/apache/commons/lang3/reflect/MemberUtils.java
index 7be7e2b48..1094190fd 100644
--- a/src/main/java/org/apache/commons/lang3/reflect/MemberUtils.java
+++ b/src/main/java/org/apache/commons/lang3/reflect/MemberUtils.java
@@ -252,7 +252,7 @@ private static boolean isMatchingExecutable(final 
Executable method, final Class
         if (ClassUtils.isAssignable(parameterTypes, methodParameterTypes, 
true)) {
             return true;
         }
-        if (method.isVarArgs()) {
+        if (method.isVarArgs() && parameterTypes.length >= 
methodParameterTypes.length - 1) {
             int i;
             for (i = 0; i < methodParameterTypes.length - 1 && i < 
parameterTypes.length; i++) {
                 if (!ClassUtils.isAssignable(parameterTypes[i], 
methodParameterTypes[i], true)) {
diff --git 
a/src/test/java/org/apache/commons/lang3/reflect/ConstructorUtilsTest.java 
b/src/test/java/org/apache/commons/lang3/reflect/ConstructorUtilsTest.java
index 93c52313a..b8c81ddfd 100644
--- a/src/test/java/org/apache/commons/lang3/reflect/ConstructorUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/reflect/ConstructorUtilsTest.java
@@ -143,6 +143,13 @@ void verify(final String str, final String[] args) {
         }
     }
 
+    public static class VarArgsBean {
+
+        public VarArgsBean(final String first, final String... rest) {
+            // empty
+        }
+    }
+
     private final Map<Class<?>, Class<?>[]> classCache;
 
     public ConstructorUtilsTest() {
@@ -246,6 +253,12 @@ void testInvokeConstructorOnNonPublicClass() {
         assertThrows(NoSuchMethodException.class, () -> 
ConstructorUtils.invokeConstructor(PrivateClass.PublicInnerClass.class));
     }
 
+    @Test
+    void testInvokeConstructorVarArgsTooFewArguments() {
+        
assertNull(ConstructorUtils.getMatchingAccessibleConstructor(VarArgsBean.class));
+        assertThrows(NoSuchMethodException.class, () -> 
ConstructorUtils.invokeConstructor(VarArgsBean.class));
+    }
+
     @Test
     void testInvokeExactConstructor() throws Exception {
         assertEquals("()", 
ConstructorUtils.invokeExactConstructor(TestBean.class, (Object[]) 
ArrayUtils.EMPTY_CLASS_ARRAY).toString());
diff --git 
a/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java 
b/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java
index 405c73191..947145999 100644
--- a/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java
@@ -1168,6 +1168,9 @@ void testInvokeMethod1PlusVarArgs() throws Exception {
         assertEquals("int, int...", MethodUtils.invokeMethod(testBean, 
"intIntVarArg", 1, 2));
         assertEquals("int, int...", MethodUtils.invokeMethod(testBean, 
"intIntVarArg", 1, 2, 3));
         assertThrows(NoSuchMethodException.class, () -> 
MethodUtils.invokeMethod(testBean, "intLongVarArg", 1, "s1", 5));
+        // too few arguments for the fixed parameters
+        assertThrows(NoSuchMethodException.class, () -> 
MethodUtils.invokeMethod(testBean, "intStringVarArg"));
+        assertNull(MethodUtils.getMatchingAccessibleMethod(TestBean.class, 
"intStringVarArg"));
     }
 
     @Test
@@ -1346,6 +1349,9 @@ void testInvokeStaticMethod1PlusVarArgs() throws 
Exception {
         assertEquals("static int, int...", MethodUtils.invokeMethod(testBean, 
"staticIntIntVarArg", 1, 2));
         assertEquals("static int, int...", MethodUtils.invokeMethod(testBean, 
"staticIntIntVarArg", 1, 2, 3));
         assertThrows(NoSuchMethodException.class, () -> 
MethodUtils.invokeMethod(testBean, "staticIntIntVarArg", 1, "s1", 5));
+        // too few arguments for the fixed parameters
+        assertThrows(NoSuchMethodException.class, () -> 
MethodUtils.invokeStaticMethod(TestBean.class, "staticIntStringVarArg"));
+        assertThrows(NoSuchMethodException.class, () -> 
MethodUtils.invokeStaticMethod(String.class, "format"));
     }
 
     @Test

Reply via email to