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

rmaucher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 1d672d78c8295c7545148c2fbcc2b1aa403baa84
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 049e6882aa..2621d42c2b 100644
--- a/java/org/apache/el/parser/AstFunction.java
+++ b/java/org/apache/el/parser/AstFunction.java
@@ -124,13 +124,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 e0ae0f6be8..2137afe565 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 jakarta.el.ELContext;
+import jakarta.el.ELException;
 import jakarta.el.ELProcessor;
 import jakarta.el.ExpressionFactory;
 import jakarta.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