From 8bbe1949e17d58e1b5aef9c71e1279ad12ad7ba7 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Wed, 11 Nov 2020 07:28:07 +0100 Subject: [PATCH] Avoids recursion in tags --- .../apache/struts2/components/Component.java | 11 +++++++++- .../org/apache/struts2/components/UIBean.java | 15 ++++++------- .../struts2/views/jsp/ui/AbstractUITag.java | 8 ++----- .../apache/struts2/components/UIBeanTest.java | 21 +++++++++++++++++++ .../apache/struts2/util/StrutsUtilTest.java | 15 +++++++++++++ .../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 e6c13d35b..9d6742fa9 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; @@ -382,6 +382,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 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 f584f9796..8c29beb4b 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 tagDynamicAttributes) { - for (Map.Entry entry : tagDynamicAttributes.entrySet()) { + public void setDynamicAttributes(Map tagDynamicAttributes) { + for (Map.Entry 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 3e4b8db42..677892efe 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 dynamicAttributes = new HashMap<>(); + protected Map 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 3e8547e6e..387d6b591 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 28c4b3406..02be0f287 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 00f17fce0..f35c03e8d 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 scriptingAttrs = new HashMap<>(); - private Map commonAttrs = new HashMap<>(); - private Map dynamicAttrs = new HashMap<>(); + + private final Map scriptingAttrs = new HashMap<>(); + private final Map commonAttrs = new HashMap<>(); + private final Map dynamicAttrs = new HashMap<>(); protected SimpleTheme theme; protected StringWriter writer; - protected Map map; + protected Map map; protected Template template; protected Map 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 entry : dynamicAttrs.entrySet()) { + for (Map.Entry entry : dynamicAttrs.entrySet()) { String substr = entry.getKey() + "=\"" + entry.getValue() + "\""; assertTrue("String [" + substr + "] was not found in [" + str + "]", str.contains(substr)); }