Skip to content

Commit 5d79301

Browse files
committed
WW-5352 Fix missing curved bracket
1 parent e9154b9 commit 5d79301

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

core/src/main/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsChecker.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@
2525
import org.apache.logging.log4j.Logger;
2626
import org.apache.struts2.StrutsConstants;
2727

28-
import java.util.Arrays;
29-
import java.util.Collections;
3028
import java.util.HashSet;
3129
import java.util.Set;
3230
import java.util.regex.Pattern;
3331

32+
import static java.util.Arrays.asList;
33+
import static java.util.Collections.unmodifiableSet;
34+
3435
public class DefaultAcceptedPatternsChecker implements AcceptedPatternsChecker {
3536

3637
private static final Logger LOG = LogManager.getLogger(DefaultAcceptedPatternsChecker.class);
@@ -39,6 +40,11 @@ public class DefaultAcceptedPatternsChecker implements AcceptedPatternsChecker {
3940
"\\w+((\\.\\w+)|(\\[\\d+])|(\\(\\d+\\))|(\\['(\\w-?|[\\u4e00-\\u9fa5]-?)+'])|(\\('(\\w-?|[\\u4e00-\\u9fa5]-?)+'\\)))*"
4041
};
4142

43+
/**
44+
* Must match {@link #ACCEPTED_PATTERNS} RegEx. Signifies characters which result in a nested lookup via OGNL.
45+
*/
46+
public static final Set<Character> NESTING_CHARS = unmodifiableSet(new HashSet<>(asList('.', '[', '(')));
47+
4248
public static final String[] DMI_AWARE_ACCEPTED_PATTERNS = {
4349
"\\w+([:]?\\w+)?((\\.\\w+)|(\\[\\d+])|(\\(\\d+\\))|(\\['(\\w-?|[\\u4e00-\\u9fa5]-?)+'])|(\\('(\\w-?|[\\u4e00-\\u9fa5]-?)+'\\)))*([!]?\\w+)?"
4450
};
@@ -74,7 +80,7 @@ protected void setAdditionalAcceptedPatterns(String acceptablePatterns) {
7480
newAcceptedPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
7581
}
7682
} finally {
77-
acceptedPatterns = Collections.unmodifiableSet(newAcceptedPatterns);
83+
acceptedPatterns = unmodifiableSet(newAcceptedPatterns);
7884
}
7985
}
8086

@@ -85,7 +91,7 @@ public void setAcceptedPatterns(String commaDelimitedPatterns) {
8591

8692
@Override
8793
public void setAcceptedPatterns(String[] additionalPatterns) {
88-
setAcceptedPatterns(new HashSet<>(Arrays.asList(additionalPatterns)));
94+
setAcceptedPatterns(new HashSet<>(asList(additionalPatterns)));
8995
}
9096

9197
@Override
@@ -97,7 +103,7 @@ public void setAcceptedPatterns(Set<String> patterns) {
97103
newAcceptedPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
98104
}
99105
} finally {
100-
acceptedPatterns = Collections.unmodifiableSet(newAcceptedPatterns);
106+
acceptedPatterns = unmodifiableSet(newAcceptedPatterns);
101107
}
102108
}
103109

core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import java.util.TreeMap;
6363
import java.util.regex.Pattern;
6464

65+
import static com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker.NESTING_CHARS;
6566
import static java.util.Collections.unmodifiableSet;
6667
import static java.util.stream.Collectors.joining;
6768
import static org.apache.commons.lang3.StringUtils.indexOfAny;
@@ -341,17 +342,17 @@ protected boolean isAcceptableParameterNameAware(String name, Object action) {
341342
* Checks if the Action class member corresponding to a parameter is appropriately annotated with
342343
* {@link StrutsParameter} and OGNL allowlists any necessary classes.
343344
* <p>
344-
* Note that this logic relies on the use of {@link DefaultAcceptedPatternsChecker#ACCEPTED_PATTERNS} and may also
345+
* Note that this logic relies on the use of {@link DefaultAcceptedPatternsChecker#NESTING_CHARS} and may also
345346
* be adversely impacted by the use of custom OGNL property accessors.
346347
*/
347348
protected boolean isParameterAnnotatedAndAllowlist(String name, Object action) {
348349
if (!requireAnnotations) {
349350
return true;
350351
}
351352

352-
int nestingIndex = indexOfAny(name, ".[");
353+
int nestingIndex = indexOfAny(name, NESTING_CHARS.stream().map(String::valueOf).collect(joining()));
353354
String rootProperty = nestingIndex == -1 ? name : name.substring(0, nestingIndex);
354-
long paramDepth = name.chars().filter(ch -> ch == '.' || ch == '[').count();
355+
long paramDepth = name.codePoints().mapToObj(c -> (char) c).filter(NESTING_CHARS::contains).count();
355356

356357
return hasValidAnnotatedMember(rootProperty, action, paramDepth);
357358
}

core/src/test/java/org/apache/struts2/interceptor/parameter/StrutsParameterAnnotationTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ public void publicPojoDepthOne() {
109109
assertThat(threadAllowlist.getAllowlist()).containsExactly(Pojo.class);
110110
}
111111

112+
@Test
113+
public void publicPojoDepthOne_sqrBracket() {
114+
testParameter(new FieldAction(), "publicPojoDepthOne['key']", true);
115+
assertThat(threadAllowlist.getAllowlist()).containsExactly(Pojo.class);
116+
}
117+
118+
@Test
119+
public void publicPojoDepthOne_bracket() {
120+
testParameter(new FieldAction(), "publicPojoDepthOne('key')", true);
121+
assertThat(threadAllowlist.getAllowlist()).containsExactly(Pojo.class);
122+
}
123+
112124
@Test
113125
public void publicNestedPojoDepthOne() {
114126
testParameter(new FieldAction(), "publicPojoDepthOne.key.key", false);
@@ -126,6 +138,18 @@ public void publicNestedPojoDepthTwo() {
126138
assertThat(threadAllowlist.getAllowlist()).containsExactly(Pojo.class);
127139
}
128140

141+
@Test
142+
public void publicNestedPojoDepthTwo_sqrBracket() {
143+
testParameter(new FieldAction(), "publicPojoDepthTwo['key']['key']", true);
144+
assertThat(threadAllowlist.getAllowlist()).containsExactly(Pojo.class);
145+
}
146+
147+
@Test
148+
public void publicNestedPojoDepthTwo_bracket() {
149+
testParameter(new FieldAction(), "publicPojoDepthTwo('key')('key')", true);
150+
assertThat(threadAllowlist.getAllowlist()).containsExactly(Pojo.class);
151+
}
152+
129153
@Test
130154
public void privateStrAnnotatedMethod() {
131155
testParameter(new MethodAction(), "privateStr", false);

0 commit comments

Comments
 (0)