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 b94e17b921898102c0c1b7f0b51fb28f1b18810d Author: opencode <[email protected]> AuthorDate: Sun Oct 18 14:25:17 2026 +0200 Reject multiple parameter sets for EL constructor and static calls When an unprefixed function call resolved through the import handler, to a class (constructor invocation) or a static import (static method invocation), AstFunction evaluated only the first set of method parameters and silently discarded any additional sets. Expressions such as ${Integer(1000)(2000)} and, with String.valueOf statically imported, ${valueOf('a')('b')} quietly ignored the trailing sets and returned the single-set result. The other two resolution paths in the same method already reject extra sets: the declared-function path raises error.function.tooManyMethodParameterSets and the lambda path raises error.lambda.tooManyMethodParameterSets after consuming one set per nested lambda. Only the lambda path supports chained parameter sets, since only a lambda can return something callable. Apply the same rule as the declared-function path to the constructor and static method dispatch, merging the two branches so the check runs once before invocation. The check sits inside the resolution guard so names that resolve to neither a class nor a static method continue to report the existing function-not-found error. Adds tests for both resolved paths and a test pinning the unchanged error for unresolved names. --- java/org/apache/el/parser/AstFunction.java | 17 +++++++--- test/org/apache/el/parser/TestAstFunction.java | 46 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/java/org/apache/el/parser/AstFunction.java b/java/org/apache/el/parser/AstFunction.java index 9e1b0cec9a..8071ef1b60 100644 --- a/java/org/apache/el/parser/AstFunction.java +++ b/java/org/apache/el/parser/AstFunction.java @@ -129,13 +129,20 @@ public final class AstFunction extends SimpleNode { // Call to a constructor or a static method obj = ctx.getImportHandler().resolveClass(this.localName); - if (obj != null) { - return ctx.getELResolver().invoke(ctx, new ELClass((Class<?>) obj), "<init>", null, - ((AstMethodParameters) this.children[0]).getParameters(ctx)); + String methodName = "<init>"; + if (obj == null) { + obj = ctx.getImportHandler().resolveStatic(this.localName); + methodName = this.localName; } - obj = ctx.getImportHandler().resolveStatic(this.localName); if (obj != null) { - return ctx.getELResolver().invoke(ctx, new ELClass((Class<?>) obj), this.localName, null, + // The result of a constructor or static method call is not + // treated as a lambda expression so there must be just a single + // set of method parameters + if (this.jjtGetNumChildren() != 1) { + throw new ELException(MessageFactory.get("error.function.tooManyMethodParameterSets", + getOutputName())); + } + return ctx.getELResolver().invoke(ctx, new ELClass((Class<?>) obj), methodName, null, ((AstMethodParameters) this.children[0]).getParameters(ctx)); } } diff --git a/test/org/apache/el/parser/TestAstFunction.java b/test/org/apache/el/parser/TestAstFunction.java index a44bb53b92..3cb818dd36 100644 --- a/test/org/apache/el/parser/TestAstFunction.java +++ b/test/org/apache/el/parser/TestAstFunction.java @@ -17,6 +17,7 @@ package org.apache.el.parser; import javax.el.ELContext; +import javax.el.ELException; import javax.el.ELProcessor; import javax.el.ExpressionFactory; import javax.el.StandardELContext; @@ -43,6 +44,51 @@ public class TestAstFunction { Assert.assertEquals(Integer.valueOf(1000), result); } + @Test + public void testImportConstructorTooManyParameterSets() { + // resolveClass path: the result of a constructor call is not treated as + // a lambda so only a single set of method parameters is valid. The extra + // set must be rejected rather than silently ignored. + ELProcessor processor = new ELProcessor(); + try { + processor.getValue("Integer(1000)(2000)", Object.class); + Assert.fail("An ELException was expected"); + } catch (ELException e) { + // Expected + } + } + + @Test + public void testImportStaticTooManyParameterSets() { + // resolveStatic path: the result of a static method call is not treated + // as a lambda so only a single set of method parameters is valid. The + // extra set must be rejected rather than silently ignored. + ELProcessor processor = new ELProcessor(); + processor.getELManager().getELContext().getImportHandler().importStatic("java.lang.String.valueOf"); + try { + processor.getValue("valueOf('a')('b')", Object.class); + Assert.fail("An ELException was expected"); + } catch (ELException e) { + // Expected + } + } + + @Test + public void testUnresolvedNameTooManyParameterSets() { + // A name that resolves to neither a class nor a static method must still + // report the "function not found" error, not the too-many-parameters + // error. This pins the placement of the parameter-set check so that it + // cannot be hoisted above the resolution. + ELProcessor processor = new ELProcessor(); + try { + processor.getValue("unknown(1)(2)", Object.class); + Assert.fail("An ELException was expected"); + } catch (ELException e) { + Assert.assertTrue("Unexpected message: " + e.getMessage(), + e.getMessage().contains("not found")); + } + } + @Test public void testVarargMethod() throws NoSuchMethodException, SecurityException { ExpressionFactory factory = ExpressionFactory.newInstance(); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
