This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new d29115004e Fix BZ 70297 - Evaluate a single EL function varargs
argument once (#1130)
d29115004e is described below
commit d29115004e9933fa8c56c105cd0d4275c36fedfd
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 ++++++++++++++
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/java/org/apache/el/parser/AstFunction.java
b/java/org/apache/el/parser/AstFunction.java
index 2621d42c2b..edac458c20 100644
--- a/java/org/apache/el/parser/AstFunction.java
+++ b/java/org/apache/el/parser/AstFunction.java
@@ -170,9 +170,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 2137afe565..7604c89144 100644
--- a/test/org/apache/el/parser/TestAstFunction.java
+++ b/test/org/apache/el/parser/TestAstFunction.java
@@ -25,6 +25,7 @@ import jakarta.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
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]