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

lukaszlenart pushed a commit to branch WW-5095-cherry-pick
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 8bbe1949e17d58e1b5aef9c71e1279ad12ad7ba7
Author: Lukasz Lenart <lukaszlen...@apache.org>
AuthorDate: Wed Nov 11 07:28:07 2020 +0100

    Avoids recursion in tags
---
 .../org/apache/struts2/components/Component.java    | 11 ++++++++++-
 .../java/org/apache/struts2/components/UIBean.java  | 15 ++++++++-------
 .../apache/struts2/views/jsp/ui/AbstractUITag.java  |  8 ++------
 .../org/apache/struts2/components/UIBeanTest.java   | 21 +++++++++++++++++++++
 .../org/apache/struts2/util/StrutsUtilTest.java     | 15 +++++++++++++++
 .../struts2/views/java/simple/AbstractTest.java     | 14 +++++++-------
 6 files changed, 63 insertions(+), 21 deletions(-)

diff --git a/core/src/main/java/org/apache/struts2/components/Component.java 
b/core/src/main/java/org/apache/struts2/components/Component.java
index e6c13d3..9d6742f 100644
--- a/core/src/main/java/org/apache/struts2/components/Component.java
+++ b/core/src/main/java/org/apache/struts2/components/Component.java
@@ -300,7 +300,7 @@ public class Component {
      * expression otherwise.
      */
        protected String completeExpressionIfAltSyntax(String expr) {
-               if (altSyntax()) {
+               if (altSyntax() && !ComponentUtils.containsExpression(expr)) {
                        return "%{" + expr + "}";
                }
                return expr;
@@ -383,6 +383,15 @@ public class Component {
     }
 
     /**
+     * Detects if altSyntax is enabled and then checks if expression contains 
%{...}
+     * @param expr a string to examined
+     * @return true if altSyntax is enabled and expr contains %{...}
+     */
+    protected boolean recursion(String expr) {
+        return ComponentUtils.altSyntax(stack) && 
ComponentUtils.containsExpression(expr);
+    }
+
+    /**
      * Renders an action URL by consulting the {@link 
org.apache.struts2.dispatcher.mapper.ActionMapper}.
      * @param action      the action
      * @param namespace   the namespace
diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java 
b/core/src/main/java/org/apache/struts2/components/UIBean.java
index f584f97..8c29beb 100644
--- a/core/src/main/java/org/apache/struts2/components/UIBean.java
+++ b/core/src/main/java/org/apache/struts2/components/UIBean.java
@@ -795,8 +795,11 @@ public abstract class UIBean extends Component {
                         addParameter("nameValue", findValue(value, 
valueClazz));
                     } else if (name != null) {
                         String expr = completeExpressionIfAltSyntax(name);
-
-                        addParameter("nameValue", findValue(expr, valueClazz));
+                        if (recursion(name)) {
+                            addParameter("nameValue", expr);
+                        } else {
+                            addParameter("nameValue", findValue(expr, 
valueClazz));
+                        }
                     }
                 } else {
                     if (value != null) {
@@ -1030,9 +1033,7 @@ public abstract class UIBean extends Component {
 
     @StrutsTagAttribute(description="HTML id attribute")
     public void setId(String id) {
-        if (id != null) {
-            this.id = findString(id);
-        }
+        this.id = id;
     }
 
     @StrutsTagAttribute(description="The template directory.")
@@ -1250,8 +1251,8 @@ public abstract class UIBean extends Component {
         this.tooltipIconPath = tooltipIconPath;
     }
 
-    public void setDynamicAttributes(Map<String, Object> tagDynamicAttributes) 
{
-        for (Map.Entry<String, Object> entry : 
tagDynamicAttributes.entrySet()) {
+    public void setDynamicAttributes(Map<String, String> tagDynamicAttributes) 
{
+        for (Map.Entry<String, String> entry : 
tagDynamicAttributes.entrySet()) {
             String key = entry.getKey();
 
             if (!isValidTagAttribute(key)) {
diff --git 
a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java 
b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java
index 3e4b8db..677892e 100644
--- a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java
+++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java
@@ -78,7 +78,7 @@ public abstract class AbstractUITag extends 
ComponentTagSupport implements Dynam
     protected String tooltipIconPath;
 
     // dynamic attributes.
-    protected Map<String, Object> dynamicAttributes = new HashMap<>();
+    protected Map<String, String> dynamicAttributes = new HashMap<>();
 
     protected void populateParams() {
         super.populateParams();
@@ -302,11 +302,7 @@ public abstract class AbstractUITag extends 
ComponentTagSupport implements Dynam
     }
 
     public void setDynamicAttribute(String uri, String localName, Object 
value) throws JspException {
-        if (ComponentUtils.altSyntax(getStack()) && 
ComponentUtils.isExpression(value.toString())) {
-            dynamicAttributes.put(localName, 
String.valueOf(ObjectUtils.defaultIfNull(findValue(value.toString()), value)));
-        } else {
-            dynamicAttributes.put(localName, value);
-        }
+        dynamicAttributes.put(localName, String.valueOf(value));
     }
 
 }
diff --git a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java 
b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
index 3e8547e..387d6b5 100644
--- a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
+++ b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
@@ -281,6 +281,27 @@ public class UIBeanTest extends StrutsInternalTestCase {
         assertEquals(value, txtFld.getParameters().get("nameValue"));
     }
 
+    public void testValueParameterRecursion() {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        MockHttpServletRequest req = new MockHttpServletRequest();
+        MockHttpServletResponse res = new MockHttpServletResponse();
+
+        stack.push(new Object() {
+            public String getMyValue() {
+                return "%{myBad}";
+            }
+            public String getMyBad() {
+                throw new IllegalStateException("Recursion detected!");
+            }
+        });
+
+        TextField txtFld = new TextField(stack, req, res);
+        txtFld.setName("%{myValue}");
+        txtFld.evaluateParams();
+
+        assertEquals("%{myBad}", txtFld.getParameters().get("nameValue"));
+    }
+
     public void testSetClass() {
         String cssClass = "insertCssClassHere";
         ValueStack stack = ActionContext.getContext().getValueStack();
diff --git a/core/src/test/java/org/apache/struts2/util/StrutsUtilTest.java 
b/core/src/test/java/org/apache/struts2/util/StrutsUtilTest.java
index 28c4b34..02be0f2 100644
--- a/core/src/test/java/org/apache/struts2/util/StrutsUtilTest.java
+++ b/core/src/test/java/org/apache/struts2/util/StrutsUtilTest.java
@@ -189,6 +189,21 @@ public class StrutsUtilTest extends StrutsInternalTestCase 
{
         assertEquals(obj1, "try: bar");
     }
 
+    public void testTranslateVariablesRecursion() throws Exception {
+        stack.push(new Object() {
+            public String getFoo() {
+                return "%{bar}";
+            }
+            public String getBar() {
+                return "bar";
+            }
+        });
+        String obj1 = strutsUtil.translateVariables("try: %{foo}");
+
+        assertNotNull(obj1);
+        assertEquals("try: %{bar}", obj1);
+    }
+
     // === Junit Hook
 
     protected void setUp() throws Exception {
diff --git 
a/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/AbstractTest.java
 
b/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/AbstractTest.java
index 00f17fc..f35c03e 100644
--- 
a/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/AbstractTest.java
+++ 
b/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/AbstractTest.java
@@ -21,7 +21,6 @@
 
 package org.apache.struts2.views.java.simple;
 
-import com.opensymphony.xwork2.Action;
 import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
 import com.opensymphony.xwork2.inject.Container;
@@ -48,14 +47,15 @@ import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 
 public abstract class AbstractTest extends TestCase {
-    private Map<String, String> scriptingAttrs = new HashMap<>();
-    private Map<String, String> commonAttrs = new HashMap<>();
-    private Map<String, Object> dynamicAttrs = new HashMap<>();
+
+    private final Map<String, String> scriptingAttrs = new HashMap<>();
+    private final Map<String, String> commonAttrs = new HashMap<>();
+    private final Map<String, String> dynamicAttrs = new HashMap<>();
 
     protected SimpleTheme theme;
 
     protected StringWriter writer;
-    protected Map map;
+    protected Map<String, Object> map;
 
     protected Template template;
     protected Map<String, Object> stackContext;
@@ -101,7 +101,7 @@ public abstract class AbstractTest extends TestCase {
         stackContext = new HashMap<>();
 
         context = new TemplateRenderingContext(template, writer, stack, map, 
null);
-        stackContext.put(Component.COMPONENT_STACK, new Stack());
+        stackContext.put(Component.COMPONENT_STACK, new Stack<>());
         ActionContext actionContext = ActionContext.of(stackContext).bind();
 
         request = createNiceMock(HttpServletRequest.class);
@@ -183,7 +183,7 @@ public abstract class AbstractTest extends TestCase {
     }
 
     protected void assertDynamicAttrs(String str) {
-        for (Map.Entry<String, Object> entry : dynamicAttrs.entrySet()) {
+        for (Map.Entry<String, String> entry : dynamicAttrs.entrySet()) {
             String substr = entry.getKey() + "=\"" + entry.getValue() + "\"";
             assertTrue("String [" + substr + "] was not found in [" + str + 
"]", str.contains(substr));
         }

Reply via email to