You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2013/06/06 07:29:49 UTC
svn commit: r1490149 - in /struts/struts2/trunk: ./
core/src/main/java/org/apache/struts2/
core/src/main/java/org/apache/struts2/dispatcher/mapper/
core/src/test/java/org/apache/struts2/dispatcher/mapper/
xwork-core/src/main/java/com/opensymphony/xwork...
Author: lukaszlenart
Date: Thu Jun 6 05:29:48 2013
New Revision: 1490149
URL: http://svn.apache.org/r1490149
Log:
Merged from STRUTS_2_3_14_2_X
WW-4090 Itroduces actions names' whitelisting [from revision 1488895]
WW-4090 Removes double evaluation of parsed expression [from revision 1488897]
WW-4090 Add some logging [from revision 1488899]
WW-4090 Uses warn level instead of debug [from revision 1488900]
Modified:
struts/struts2/trunk/ (props changed)
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/util/OgnlTextParser.java
struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java
Propchange: struts/struts2/trunk/
------------------------------------------------------------------------------
Merged /struts/struts2/branches/STRUTS_2_3_14_2_X:r1488895,1488897,1488899-1488900
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java?rev=1490149&r1=1490148&r2=1490149&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java Thu Jun 6 05:29:48 2013
@@ -252,4 +252,7 @@ public final class StrutsConstants {
public static final String STRUTS_EXPRESSION_PARSER = "struts.expression.parser";
+ /** actions names' whitelist **/
+ public static final String STRUTS_ALLOWED_ACTION_NAMES = "struts.allowed.action.names";
+
}
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java?rev=1490149&r1=1490148&r2=1490149&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java Thu Jun 6 05:29:48 2013
@@ -27,6 +27,8 @@ import com.opensymphony.xwork2.config.Co
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.RequestUtils;
import org.apache.struts2.ServletActionContext;
@@ -35,12 +37,7 @@ import org.apache.struts2.dispatcher.Ser
import org.apache.struts2.util.PrefixTrie;
import javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
/**
* <!-- START SNIPPET: javadoc -->
@@ -162,6 +159,8 @@ import java.util.Set;
*/
public class DefaultActionMapper implements ActionMapper {
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultActionMapper.class);
+
protected static final String METHOD_PREFIX = "method:";
protected static final String ACTION_PREFIX = "action:";
protected static final String REDIRECT_PREFIX = "redirect:";
@@ -171,6 +170,7 @@ public class DefaultActionMapper impleme
protected boolean allowSlashesInActionNames = false;
protected boolean alwaysSelectFullNamespace = false;
protected PrefixTrie prefixTrie = null;
+ protected String allowedActionNames = "[a-z]*[A-Z]*[0-9]*[.\\-_!/]*";
protected List<String> extensions = new ArrayList<String>() {{
add("action");
@@ -260,6 +260,11 @@ public class DefaultActionMapper impleme
this.alwaysSelectFullNamespace = "true".equals(val);
}
+ @Inject(value = StrutsConstants.STRUTS_ALLOWED_ACTION_NAMES, required = false)
+ public void setAllowedActionNames(String allowedActionNames) {
+ this.allowedActionNames = allowedActionNames;
+ }
+
@Inject
public void setContainer(Container container) {
this.container = container;
@@ -417,7 +422,32 @@ public class DefaultActionMapper impleme
}
mapping.setNamespace(namespace);
- mapping.setName(name);
+ mapping.setName(cleanupActionName(name));
+ }
+
+ /**
+ * Cleans up action name from suspicious characters
+ *
+ * @param rawActionName action name extracted from URI
+ * @return safe action name
+ */
+ protected String cleanupActionName(final String rawActionName) {
+ if (rawActionName.matches(allowedActionNames)) {
+ return rawActionName;
+ } else {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Action [#0] do not match allowed action names pattern [#1], cleaning it up!",
+ rawActionName, allowedActionNames);
+ }
+ String cleanActionName = rawActionName;
+ for(String chunk : rawActionName.split(allowedActionNames)) {
+ cleanActionName = cleanActionName.replace(chunk, "");
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Cleaned action name [#0]", cleanActionName);
+ }
+ return cleanActionName;
+ }
}
/**
Modified: struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java?rev=1490149&r1=1490148&r2=1490149&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java (original)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java Thu Jun 6 05:29:48 2013
@@ -747,4 +747,23 @@ public class DefaultActionMapperTest ext
}
+ public void testAllowedActionNames() throws Exception {
+ DefaultActionMapper mapper = new DefaultActionMapper();
+
+ String actionName = "action";
+ assertEquals(actionName, mapper.cleanupActionName(actionName));
+
+ actionName = "${action}";
+ assertEquals("action", mapper.cleanupActionName(actionName));
+
+ actionName = "${${%{action}}}";
+ assertEquals("action", mapper.cleanupActionName(actionName));
+
+ actionName = "${#foo='action',#foo}";
+ assertEquals("fooactionfoo", mapper.cleanupActionName(actionName));
+
+ actionName = "test-action";
+ assertEquals("test-action", mapper.cleanupActionName(actionName));
+ }
+
}
Modified: struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/util/OgnlTextParser.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/util/OgnlTextParser.java?rev=1490149&r1=1490148&r2=1490149&view=diff
==============================================================================
--- struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/util/OgnlTextParser.java (original)
+++ struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/util/OgnlTextParser.java Thu Jun 6 05:29:48 2013
@@ -11,17 +11,16 @@ public class OgnlTextParser implements T
// deal with the "pure" expressions first!
//expression = expression.trim();
Object result = expression;
+ int pos = 0;
+
for (char open : openChars) {
int loopCount = 1;
- int pos = 0;
-
//this creates an implicit StringBuffer and shouldn't be used in the inner loop
final String lookupChars = open + "{";
while (true) {
int start = expression.indexOf(lookupChars, pos);
if (start == -1) {
- pos = 0;
loopCount++;
start = expression.indexOf(lookupChars);
}
Modified: struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java?rev=1490149&r1=1490148&r2=1490149&view=diff
==============================================================================
--- struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java (original)
+++ struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/util/TextParseUtilTest.java Thu Jun 6 05:29:48 2013
@@ -97,6 +97,24 @@ public class TextParseUtilTest extends X
assertEquals("count must be between 123 and 456, current value is 98765.", s);
}
+ public void testNestedExpression() throws Exception {
+ ValueStack stack = ActionContext.getContext().getValueStack();
+ stack.push(new HashMap<String, Object>() {{ put("foo", "${%{1+1}}"); }});
+ String s = TextParseUtil.translateVariables("${foo}", stack);
+ assertEquals("${%{1+1}}", s);
+ stack.pop();
+ }
+
+ public void testMixedOpenChars() throws Exception {
+ ValueStack stack = ActionContext.getContext().getValueStack();
+ stack.push(new HashMap<String, Object>() {{ put("foo", "bar"); }});
+ String s = TextParseUtil.translateVariables("${foo}-%{foo}", stack);
+ assertEquals("bar-bar", s);
+ s = TextParseUtil.translateVariables("%{foo}-${foo}", stack);
+ assertEquals("%{foo}-bar", s); // this is bad, but it is the only way not to double evaluate passed expression
+ stack.pop();
+ }
+
public void testCommaDelimitedStringToSet() {
assertEquals(0, TextParseUtil.commaDelimitedStringToSet("").size());
assertEquals(new HashSet<String>(Arrays.asList("foo", "bar", "tee")),
@@ -132,10 +150,13 @@ public class TextParseUtilTest extends X
public void testTranslateVariablesRecursive() {
ValueStack stack = ActionContext.getContext().getValueStack();
- stack.push(new HashMap<String, Object>() {{ put("foo", "${1+1}"); }});
+ stack.push(new HashMap<String, Object>() {{ put("foo", "${1+1}"); put("bar", "${${1+2}}"); }});
Object s = TextParseUtil.translateVariables('$', "foo: ${foo}", stack, String.class, null, 2);
assertEquals("foo: 2", s);
+
+ s = TextParseUtil.translateVariables('$', "foo: ${bar}", stack, String.class, null, 1);
+ assertEquals("foo: ${${1+2}}", s);
}
public void testTranslateVariablesWithNull() {