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

markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new 7e196972fb Fix BZ 70297 - Evaluate a single EL function varargs 
argument once (#1130)
7e196972fb is described below

commit 7e196972fb9139357aea1f8fb4fcffad59d2ddac
Author: Mykola Pavluchynskyi <[email protected]>
AuthorDate: Thu Nov 12 11:55:54 2026 +0100

    Fix BZ 70297 - Evaluate a single EL function varargs argument once (#1130)
    
    When an EL function whose method is varargs was called with exactly one
    argument for the varargs parameter, AstFunction evaluated that argument
    twice: once to check whether it is already an array and once more for the
    value. An argument with side effects ran twice, the function received the
    result of the second evaluation, and an expensive argument cost double.
    
    Evaluate the argument once and use the value both for the array check and
    as the single varargs element. Calls with two or more varargs values and
    the single array argument case are unchanged.
    
    Adds a test that counts the evaluations of a method call used as the
    single varargs argument. The test reports two evaluations against the
    previous implementation.
---
 java/org/apache/el/parser/AstFunction.java     | 13 ++++++++++---
 test/org/apache/el/parser/TestAstFunction.java | 14 ++++++++++++++
 webapps/docs/changelog.xml                     |  5 +++++
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/java/org/apache/el/parser/AstFunction.java 
b/java/org/apache/el/parser/AstFunction.java
index 8071ef1b60..6d80d7924b 100644
--- a/java/org/apache/el/parser/AstFunction.java
+++ b/java/org/apache/el/parser/AstFunction.java
@@ -175,9 +175,16 @@ public final class AstFunction extends SimpleNode {
                             // Java semantics: an empty array is passed when no
                             // varargs elements are supplied
                             params[i] = new Object[0];
-                        } else if (inputParameterCount == methodParameterCount 
&&
-                                
isArray(parameters.jjtGetChild(i).getValue(ctx))) {
-                            params[i] = 
parameters.jjtGetChild(i).getValue(ctx);
+                        } else if (inputParameterCount == 
methodParameterCount) {
+                            // Evaluate the single argument once: it is either
+                            // the varargs array itself or its only element
+                            Object value = 
parameters.jjtGetChild(i).getValue(ctx);
+                            if (isArray(value)) {
+                                params[i] = value;
+                            } else {
+                                params[i] = new Object[] { 
ELSupport.coerceToType(ctx, value,
+                                        paramTypes[i].getComponentType()) };
+                            }
                         } else {
                             Object[] varargs = new Object[inputParameterCount 
- methodParameterCount + 1];
                             Class<?> target = paramTypes[i].getComponentType();
diff --git a/test/org/apache/el/parser/TestAstFunction.java 
b/test/org/apache/el/parser/TestAstFunction.java
index 3cb818dd36..1816609895 100644
--- a/test/org/apache/el/parser/TestAstFunction.java
+++ b/test/org/apache/el/parser/TestAstFunction.java
@@ -25,6 +25,7 @@ import javax.el.StandardELContext;
 import org.junit.Assert;
 import org.junit.Test;
 
+import org.apache.el.TesterBeanK;
 import org.apache.el.TesterFunctions;
 
 public class TestAstFunction {
@@ -108,6 +109,19 @@ public class TestAstFunction {
         Assert.assertEquals("one", result);
     }
 
+    @Test
+    public void testVarargMethodSingleArgumentEvaluatedOnce() throws 
NoSuchMethodException {
+        // The argument that alone fills the varargs parameter must be 
evaluated
+        // exactly once, as each argument is when there are several
+        ELProcessor processor = new ELProcessor();
+        TesterBeanK bean = new TesterBeanK();
+        processor.defineBean("beanK", bean);
+        processor.defineFunction("fn", "format", 
String.class.getMethod("format", String.class, Object[].class));
+
+        Assert.assertEquals("1", processor.getValue("fn:format('%s', 
beanK.next())", String.class));
+        Assert.assertEquals(1, bean.argCalls);
+    }
+
     @Test
     public void testVarargMethodEmptyVarargs01() throws NoSuchMethodException {
         // Java passes an empty array, never null, to a varargs method that is
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index f6f044b77c..ec0ff3d598 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -136,6 +136,11 @@
         Improve search of existing methods when defining functions using an
         <code>ELProcressor</code>. (markt)
       </fix>
+      <fix>
+        <bug>70297</bug>: Avoid duplicate evaluation of a single vararg 
argument
+        when calling an EL function. Pull request <pr>1130</pr> by Mykola
+        Pavluchynskyi. (markt)
+      </fix>
     </changelog>
   </subsection>
 </section>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to