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]

Reply via email to