This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit f5d4d5e51fd7a05f1081e051832b465b678184ae Author: opencode <[email protected]> AuthorDate: Sun Oct 18 15:40:28 2026 +0200 Accept zero varargs elements in EL method expression calls The argument count check in AstValue.convertArgs, which prepares the arguments for a method expression invocation, rejected calls that supplied exactly the fixed parameters of a varargs method. A varargs method with N parameters accepts N minus 1 arguments, the final parameter being supplied by zero or more arguments, but the guard required N. Such calls were reported as IllegalArgumentException even though the same call written directly in the expression, and the same call through the value expression mechanism, both worked. The two invocation mechanisms disagreed on valid Java arity. Reduce the required count by one for varargs methods and report the true minimum in the too-few-parameters message. Building the trailing varargs array already handles the zero-element case for every component type. Two existing tests relied on the incorrect arity. testBug60844 asserted the rejected error for a call with one value of the wrong type against a method whose minimum arity is one; that call is now valid by arity and fails in the argument coercion with an ELException, as it would via the value expression mechanism, so the test now uses a genuinely too-few call and still pins the reported error. testStaticMethodOnInstance asserted the rejection of a call with only the format string; the call is valid and the test now asserts the correct result. Adds tests for calls with zero and one varargs elements. --- java/org/apache/el/parser/AstValue.java | 7 +++-- test/org/apache/el/TestMethodExpressionImpl.java | 35 ++++++++++++++++++++++-- test/org/apache/el/util/TestReflectionUtil.java | 19 ++++++------- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/java/org/apache/el/parser/AstValue.java b/java/org/apache/el/parser/AstValue.java index ba7c9b512a..7f0cc65111 100644 --- a/java/org/apache/el/parser/AstValue.java +++ b/java/org/apache/el/parser/AstValue.java @@ -258,7 +258,10 @@ public final class AstValue extends SimpleNode { int paramCount = types.length; - if (m.isVarArgs() && paramCount > 1 && (src == null || paramCount > src.length) || + // For a varargs method, the final parameter may be supplied by zero or + // more arguments so the minimum number of arguments is one less than + // the number of parameters. + if (m.isVarArgs() && paramCount > 1 && (src == null || paramCount - 1 > src.length) || !m.isVarArgs() && (src == null || src.length != paramCount)) { String srcCount = null; if (src != null) { @@ -267,7 +270,7 @@ public final class AstValue extends SimpleNode { String msg; if (m.isVarArgs()) { msg = MessageFactory.get("error.invoke.tooFewParams", m.getName(), srcCount, - Integer.toString(paramCount)); + Integer.toString(paramCount - 1)); } else { msg = MessageFactory.get("error.invoke.wrongParams", m.getName(), srcCount, Integer.toString(paramCount)); diff --git a/test/org/apache/el/TestMethodExpressionImpl.java b/test/org/apache/el/TestMethodExpressionImpl.java index cc5cb11186..518a10aa09 100644 --- a/test/org/apache/el/TestMethodExpressionImpl.java +++ b/test/org/apache/el/TestMethodExpressionImpl.java @@ -492,9 +492,13 @@ public class TestMethodExpressionImpl { @Test(expected = IllegalArgumentException.class) public void testBug60844() { + // Fewer parameter values than the minimum required by a varargs + // method (here, the fixed parameters only). A single value would be + // a valid number of arguments for this method, so the call below + // with no values is the too-few-parameters case. MethodExpression me2 = factory.createMethodExpression(context, "${beanC.sayHello}", null, - new Class[] { TesterBeanA.class, TesterBeanB.class }); - me2.invoke(context, new Object[] { new Object() }); + new Class[] { TesterBeanA.class }); + me2.invoke(context, new Object[] { }); } @@ -721,6 +725,33 @@ public class TestMethodExpressionImpl { } + @Test + public void testVarArgsZeroVarArgsElements() { + // A call that supplies only the fixed parameters of a varargs method + // is valid Java. The method expression mechanism must accept it, as + // the value expression mechanism already does. + context.getVariableMapper().setVariable("beanH", + factory.createValueExpression(new TesterBeanH(), TesterBeanH.class)); + + MethodExpression me = factory.createMethodExpression(context, "${beanH.doTest}", String.class, + new Class<?>[] { String.class }); + + Assert.assertEquals("String-VString", me.invoke(context, new Object[] { "apple" })); + } + + + @Test + public void testVarArgsOneVarArgsElement() { + context.getVariableMapper().setVariable("beanH", + factory.createValueExpression(new TesterBeanH(), TesterBeanH.class)); + + MethodExpression me = factory.createMethodExpression(context, "${beanH.doTest}", String.class, + new Class<?>[] { String.class, String.class }); + + Assert.assertEquals("String-VString", me.invoke(context, new Object[] { "apple", "apple" })); + } + + @Test public void testGetMethodInfo01() throws Exception { MethodExpression me = factory.createMethodExpression(context, "#{beanA.setName('New value')}", null, null); diff --git a/test/org/apache/el/util/TestReflectionUtil.java b/test/org/apache/el/util/TestReflectionUtil.java index ffac25b3bd..4dacbac2a9 100644 --- a/test/org/apache/el/util/TestReflectionUtil.java +++ b/test/org/apache/el/util/TestReflectionUtil.java @@ -72,17 +72,14 @@ public class TestReflectionUtil { ExpressionFactory factory = ExpressionFactory.newInstance(); ELContext context = new ELContextImpl(factory); - MethodExpression methodExpression = - factory.createMethodExpression(context, "${\"1\".format(2)}", String.class, new Class<?>[] {}); + MethodExpression methodExpression = factory.createMethodExpression(context, "${\"1\".format(2)}", String.class, + new Class<?>[] {}); - try { - methodExpression.invoke(context, null); - } catch (IllegalArgumentException iae) { - // Ensure correct IllegalArgumentException is thrown - String msg = iae.getMessage(); - Assert.assertTrue(msg, msg.contains("[format]")); - return; - } - Assert.fail("No exception"); + // The static method format(String,Object...) must be resolvable and + // invocable when called on an instance. The single argument is the + // format string. No varargs elements are provided which is valid. + Object result = methodExpression.invoke(context, null); + + Assert.assertEquals("2", result); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
