Skip to content

Commit 25e5006

Browse files
committed
Security patch applied
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/branches/STRUTS_2_2_3_1@1164516 13f79535-47bb-0310-9956-ffa450edef68
1 parent babac6c commit 25e5006

File tree

6 files changed

+128
-77
lines changed

6 files changed

+128
-77
lines changed

core/src/main/java/org/apache/struts2/interceptor/StrutsConversionErrorInterceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ protected Object getOverrideExpr(ActionInvocation invocation, Object value) {
8080
try {
8181
stack.push(value);
8282

83-
return "'" + stack.findValue("top", String.class) + "'";
83+
return escape(stack.findString("top"));
8484
} finally {
8585
stack.pop();
8686
}

core/src/main/resources/template/simple/text.ftl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
maxlength="${parameters.maxlength?html}"<#rt/>
3030
</#if>
3131
<#if parameters.nameValue??>
32-
value="<@s.property value="parameters.nameValue"/>"<#rt/>
32+
value="${parameters.nameValue?html}"<#rt/>
3333
</#if>
3434
<#if parameters.disabled?default(false)>
3535
disabled="disabled"<#rt/>
@@ -50,4 +50,4 @@
5050
<#include "/${parameters.templateDir}/simple/scripting-events.ftl" />
5151
<#include "/${parameters.templateDir}/simple/common-attributes.ftl" />
5252
<#include "/${parameters.templateDir}/simple/dynamic-attributes.ftl" />
53-
/>
53+
/>

core/src/test/java/org/apache/struts2/interceptor/StrutsConversionErrorInterceptorTest.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,17 @@
2121

2222
package org.apache.struts2.interceptor;
2323

24-
import java.util.HashMap;
25-
import java.util.Map;
26-
27-
import org.apache.struts2.StrutsTestCase;
28-
2924
import com.mockobjects.dynamic.C;
3025
import com.mockobjects.dynamic.Mock;
3126
import com.opensymphony.xwork2.Action;
3227
import com.opensymphony.xwork2.ActionContext;
3328
import com.opensymphony.xwork2.ActionInvocation;
3429
import com.opensymphony.xwork2.ActionSupport;
3530
import com.opensymphony.xwork2.util.ValueStack;
36-
import com.opensymphony.xwork2.util.ValueStackFactory;
31+
import org.apache.struts2.StrutsTestCase;
32+
33+
import java.util.HashMap;
34+
import java.util.Map;
3735

3836

3937
/**
@@ -44,14 +42,14 @@ public class StrutsConversionErrorInterceptorTest extends StrutsTestCase {
4442

4543
protected ActionContext context;
4644
protected ActionInvocation invocation;
47-
protected Map conversionErrors;
45+
protected Map<String, Object> conversionErrors;
4846
protected Mock mockInvocation;
4947
protected ValueStack stack;
5048
protected StrutsConversionErrorInterceptor interceptor;
5149

5250

5351
public void testEmptyValuesDoNotSetFieldErrors() throws Exception {
54-
conversionErrors.put("foo", new Long(123));
52+
conversionErrors.put("foo", 123L);
5553
conversionErrors.put("bar", "");
5654
conversionErrors.put("baz", new String[]{""});
5755

@@ -70,7 +68,7 @@ public void testEmptyValuesDoNotSetFieldErrors() throws Exception {
7068
}
7169

7270
public void testFieldErrorAdded() throws Exception {
73-
conversionErrors.put("foo", new Long(123));
71+
conversionErrors.put("foo", 123L);
7472

7573
ActionSupport action = new ActionSupport();
7674
mockInvocation.expectAndReturn("getAction", action);
@@ -89,7 +87,7 @@ protected void setUp() throws Exception {
8987
invocation = (ActionInvocation) mockInvocation.proxy();
9088
stack = ActionContext.getContext().getValueStack();
9189
context = new ActionContext(stack.getContext());
92-
conversionErrors = new HashMap();
90+
conversionErrors = new HashMap<String, Object>();
9391
context.setConversionErrors(conversionErrors);
9492
mockInvocation.matchAndReturn("getInvocationContext", context);
9593
mockInvocation.expectAndReturn("invoke", Action.SUCCESS);

xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.opensymphony.xwork2.ValidationAware;
2121
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
2222
import com.opensymphony.xwork2.util.ValueStack;
23+
import org.apache.commons.lang.StringEscapeUtils;
2324

2425
import java.util.HashMap;
2526
import java.util.Map;
@@ -84,7 +85,11 @@ public class ConversionErrorInterceptor extends AbstractInterceptor {
8485
public static final String ORIGINAL_PROPERTY_OVERRIDE = "original.property.override";
8586

8687
protected Object getOverrideExpr(ActionInvocation invocation, Object value) {
87-
return "'" + value + "'";
88+
return escape(value);
89+
}
90+
91+
protected String escape(Object value) {
92+
return "\"" + StringEscapeUtils.escapeJava(String.valueOf(value)) + "\"";
8893
}
8994

9095
@Override

xwork-core/src/main/java/com/opensymphony/xwork2/validator/validators/RepopulateConversionErrorFieldValidatorSupport.java

Lines changed: 58 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -22,58 +22,59 @@
2222
import com.opensymphony.xwork2.util.logging.Logger;
2323
import com.opensymphony.xwork2.util.logging.LoggerFactory;
2424
import com.opensymphony.xwork2.validator.ValidationException;
25+
import org.apache.commons.lang.StringEscapeUtils;
2526

2627
import java.util.LinkedHashMap;
2728
import java.util.Map;
2829

2930
/**
30-
*
31-
*
31+
*
32+
*
3233
* An abstract base class that adds in the capability to populate the stack with
3334
* a fake parameter map when a conversion error has occurred and the 'repopulateField'
3435
* property is set to "true".
35-
*
36+
*
3637
* <p/>
37-
*
38+
*
3839
*
3940
* <!-- START SNIPPET: javadoc -->
4041
*
41-
* The capability of auto-repopulating the stack with a fake parameter map when
42-
* a conversion error has occurred can be done with 'repopulateField' property
43-
* set to "true".
42+
* The capability of auto-repopulating the stack with a fake parameter map when
43+
* a conversion error has occurred can be done with 'repopulateField' property
44+
* set to "true".
4445
*
4546
* <p/>
4647
*
47-
* This is typically usefull when one wants to repopulate the field with the original value
48-
* when a conversion error occurred. Eg. with a textfield that only allows an Integer
48+
* This is typically usefull when one wants to repopulate the field with the original value
49+
* when a conversion error occurred. Eg. with a textfield that only allows an Integer
4950
* (the action class have an Integer field declared), upon conversion error, the incorrectly
5051
* entered integer (maybe a text 'one') will not appear when dispatched back. With 'repopulateField'
51-
* porperty set to true, it will, meaning the textfield will have 'one' as its value
52+
* porperty set to true, it will, meaning the textfield will have 'one' as its value
5253
* upon conversion error.
53-
*
54+
*
5455
* <!-- END SNIPPET: javadoc -->
55-
*
56+
*
5657
* <p/>
57-
*
58+
*
5859
* <pre>
5960
* <!-- START SNIPPET: exampleJspPage -->
60-
*
61+
*
6162
* &lt;!-- myJspPage.jsp --&gt;
6263
* &lt;ww:form action="someAction" method="POST"&gt;
6364
* ....
64-
* &lt;ww:textfield
65+
* &lt;ww:textfield
6566
* label="My Integer Field"
6667
* name="myIntegerField" /&gt;
6768
* ....
68-
* &lt;ww:submit /&gt;
69+
* &lt;ww:submit /&gt;
6970
* &lt;/ww:form&gt;
70-
*
71+
*
7172
* <!-- END SNIPPET: exampleJspPage -->
7273
* </pre>
73-
*
74+
*
7475
* <pre>
7576
* <!-- START SNIPPET: exampleXwork -->
76-
*
77+
*
7778
* &lt;!-- xwork.xml --&gt;
7879
* &lt;xwork&gt;
7980
* &lt;include file="xwork-default.xml" /&gt;
@@ -88,31 +89,31 @@
8889
* &lt;/package&gt;
8990
* ....
9091
* &lt;/xwork&gt;
91-
*
92+
*
9293
* <!-- END SNIPPET:exampleXwork -->
9394
* </pre>
94-
*
95-
*
95+
*
96+
*
9697
* <pre>
9798
* <!-- START SNIPPET: exampleJava -->
98-
*
99+
*
99100
* &lt;!-- MyActionSupport.java --&gt;
100101
* public class MyActionSupport extends ActionSupport {
101102
* private Integer myIntegerField;
102-
*
103+
*
103104
* public Integer getMyIntegerField() { return this.myIntegerField; }
104-
* public void setMyIntegerField(Integer myIntegerField) {
105-
* this.myIntegerField = myIntegerField;
105+
* public void setMyIntegerField(Integer myIntegerField) {
106+
* this.myIntegerField = myIntegerField;
106107
* }
107108
* }
108-
*
109+
*
109110
* <!-- END SNIPPET: exampleJava -->
110111
* </pre>
111-
*
112-
*
112+
*
113+
*
113114
* <pre>
114115
* <!-- START SNIPPET: exampleValidation -->
115-
*
116+
*
116117
* &lt;!-- MyActionSupport-someAction-validation.xml --&gt;
117118
* &lt;validators&gt;
118119
* ...
@@ -124,24 +125,24 @@
124125
* &lt;/field&gt;
125126
* ...
126127
* &lt;/validators&gt;
127-
*
128+
*
128129
* <!-- END SNIPPET: exampleValidation -->
129130
* </pre>
130-
*
131+
*
131132
* @author tm_jee
132133
* @version $Date$ $Id$
133134
*/
134135
public abstract class RepopulateConversionErrorFieldValidatorSupport extends FieldValidatorSupport {
135-
136+
136137
private static final Logger LOG = LoggerFactory.getLogger(RepopulateConversionErrorFieldValidatorSupport.class);
137-
138+
138139
private String repopulateFieldAsString = "false";
139140
private boolean repopulateFieldAsBoolean = false;
140-
141-
public String getRepopulateField() {
141+
142+
public String getRepopulateField() {
142143
return repopulateFieldAsString;
143144
}
144-
145+
145146
public void setRepopulateField(String repopulateField) {
146147
this.repopulateFieldAsString = repopulateField == null ? repopulateField : repopulateField.trim();
147148
this.repopulateFieldAsBoolean = "true".equalsIgnoreCase(this.repopulateFieldAsString) ? (true) : (false);
@@ -153,12 +154,12 @@ public void validate(Object object) throws ValidationException {
153154
repopulateField(object);
154155
}
155156
}
156-
157+
157158
public void repopulateField(Object object) throws ValidationException {
158-
159+
159160
ActionInvocation invocation = ActionContext.getContext().getActionInvocation();
160161
Map<String, Object> conversionErrors = ActionContext.getContext().getConversionErrors();
161-
162+
162163
String fieldName = getFieldName();
163164
String fullFieldName = getValidatorContext().getFullFieldName(fieldName);
164165
if (conversionErrors.containsKey(fullFieldName)) {
@@ -170,19 +171,23 @@ public void repopulateField(Object object) throws ValidationException {
170171
if (value instanceof String[]) {
171172
// take the first element, if possible
172173
String[] tmpValue = (String[]) value;
173-
if (tmpValue != null && (tmpValue.length > 0)) {
174+
if ((tmpValue.length > 0)) {
174175
doExprOverride = true;
175-
fakeParams.put(fullFieldName, "'" + tmpValue[0] + "'");
176+
fakeParams.put(fullFieldName, escape(tmpValue[0]));
176177
} else {
177-
LOG.warn("value is an empty array of String or with first element in it as null [" + value + "], will not repopulate conversion error ");
178+
if (LOG.isWarnEnabled()) {
179+
LOG.warn("value is an empty array of String or with first element in it as null [" + value + "], will not repopulate conversion error ");
180+
}
178181
}
179182
} else if (value instanceof String) {
180183
String tmpValue = (String) value;
181184
doExprOverride = true;
182-
fakeParams.put(fullFieldName, "'" + tmpValue + "'");
185+
fakeParams.put(fullFieldName, escape(tmpValue));
183186
} else {
184187
// opps... it should be
185-
LOG.warn("conversion error value is not a String or array of String but instead is [" + value + "], will not repopulate conversion error");
188+
if (LOG.isWarnEnabled()) {
189+
LOG.warn("conversion error value is not a String or array of String but instead is [" + value + "], will not repopulate conversion error");
190+
}
186191
}
187192

188193
if (doExprOverride) {
@@ -194,7 +199,11 @@ public void beforeResult(ActionInvocation invocation, String resultCode) {
194199
});
195200
}
196201
}
197-
}
198-
199-
protected abstract void doValidate(Object object) throws ValidationException;
200-
}
202+
}
203+
204+
protected String escape(String value) {
205+
return "\"" + StringEscapeUtils.escapeJava(value) + "\"";
206+
}
207+
208+
protected abstract void doValidate(Object object) throws ValidationException;
209+
}

0 commit comments

Comments
 (0)