From 1a20867d01ef8ee5b32b0620125b7c38a10b80c5 Mon Sep 17 00:00:00 2001 From: drajakumar Date: Mon, 13 Mar 2017 22:21:12 +0530 Subject: [PATCH] LANG-1310: MethodUtils.invokeMethod throws ArrayStoreException if using varargs arguments and smaller types than the method defines (closes #256) --- .../commons/lang3/reflect/MethodUtils.java | 14 ++++++++ .../lang3/reflect/MethodUtilsTest.java | 32 +++++++++++++++---- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java b/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java index 0f94d9375..46023782f 100644 --- a/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java +++ b/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java @@ -700,6 +700,20 @@ public class MethodUtils { if (bestMatch != null) { MemberUtils.setAccessibleWorkaround(bestMatch); } + + if (bestMatch != null && bestMatch.isVarArgs() && bestMatch.getParameterTypes().length > 0 && parameterTypes.length > 0) { + final Class[] methodParameterTypes = bestMatch.getParameterTypes(); + final Class methodParameterComponentType = methodParameterTypes[methodParameterTypes.length - 1].getComponentType(); + final String methodParameterComponentTypeName = ClassUtils.primitiveToWrapper(methodParameterComponentType).getName(); + final String parameterTypeName = parameterTypes[parameterTypes.length - 1].getName(); + final String parameterTypeSuperClassName = parameterTypes[parameterTypes.length - 1].getSuperclass().getName(); + + if (!methodParameterComponentTypeName.equals(parameterTypeName) + && !methodParameterComponentTypeName.equals(parameterTypeSuperClassName)) { + return null; + } + } + return bestMatch; } 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 351bed1ba..df57a13fd 100644 --- a/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java @@ -96,6 +96,10 @@ public class MethodUtilsTest { return "bar(String...)"; } + public static String bar(final long... s) { + return "bar(long...)"; + } + public static String bar(final Integer i, final String... s) { return "bar(int, String...)"; } @@ -138,7 +142,6 @@ public class MethodUtilsTest { return "privateStringStuff(Object)"; } - public String foo() { return "foo()"; } @@ -155,6 +158,10 @@ public class MethodUtilsTest { return "foo(double)"; } + public String foo(final long l) { + return "foo(long)"; + } + public String foo(final String s) { return "foo(String)"; } @@ -167,6 +174,10 @@ public class MethodUtilsTest { return "foo(String...)"; } + public String foo(final long... l) { + return "foo(long...)"; + } + public String foo(final Integer i, final String... s) { return "foo(int, String...)"; } @@ -356,7 +367,7 @@ public class MethodUtilsTest { NumberUtils.INTEGER_ONE)); assertEquals("foo(int)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.BYTE_ONE)); - assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo", + assertEquals("foo(long)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.LONG_ONE)); assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo", NumberUtils.DOUBLE_ONE)); @@ -366,6 +377,15 @@ public class MethodUtilsTest { "a", "b", "c")); assertEquals("foo(int, String...)", MethodUtils.invokeMethod(testBean, "foo", 5, "a", "b", "c")); + assertEquals("foo(long...)", MethodUtils.invokeMethod(testBean, "foo", + 1L, 2L)); + + try { + MethodUtils.invokeMethod(testBean, "foo", + 1, 2); + fail("should throw NoSuchMethodException"); + } catch (NoSuchMethodException expected) { + } TestBean.verify(new ImmutablePair("String...", new String[]{"x", "y"}), MethodUtils.invokeMethod(testBean, "varOverloadEcho", "x", "y")); @@ -433,12 +453,12 @@ public class MethodUtilsTest { TestBean.class, "bar", NumberUtils.INTEGER_ONE)); assertEquals("bar(int)", MethodUtils.invokeStaticMethod(TestBean.class, "bar", NumberUtils.BYTE_ONE)); - assertEquals("bar(double)", MethodUtils.invokeStaticMethod( - TestBean.class, "bar", NumberUtils.LONG_ONE)); assertEquals("bar(double)", MethodUtils.invokeStaticMethod( TestBean.class, "bar", NumberUtils.DOUBLE_ONE)); assertEquals("bar(String...)", MethodUtils.invokeStaticMethod( TestBean.class, "bar", "a", "b")); + assertEquals("bar(long...)", MethodUtils.invokeStaticMethod( + TestBean.class, "bar", 1L, 2L)); assertEquals("bar(int, String...)", MethodUtils.invokeStaticMethod( TestBean.class, "bar", NumberUtils.INTEGER_ONE, "a", "b")); @@ -576,9 +596,9 @@ public class MethodUtilsTest { expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Integer.TYPE), singletonArray(Integer.TYPE)); expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", - singletonArray(Long.class), singletonArray(Double.TYPE)); + singletonArray(Long.class), singletonArray(Long.TYPE)); expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", - singletonArray(Long.TYPE), singletonArray(Double.TYPE)); + singletonArray(Long.TYPE), singletonArray(Long.TYPE)); expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo", singletonArray(Float.class), singletonArray(Double.TYPE)); expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",