@@ -43,6 +43,12 @@ public class OperatorMatches extends Operator {
43
43
44
44
private static final int PATTERN_ACCESS_THRESHOLD = 1000000 ;
45
45
46
+ /**
47
+ * Maximum number of characters permitted in a regular expression.
48
+ * @since 5.2.23
49
+ */
50
+ private static final int MAX_REGEX_LENGTH = 256 ;
51
+
46
52
private final ConcurrentMap <String , Pattern > patternCache ;
47
53
48
54
@@ -78,26 +84,28 @@ public OperatorMatches(ConcurrentMap<String, Pattern> patternCache, int startPos
78
84
public BooleanTypedValue getValueInternal (ExpressionState state ) throws EvaluationException {
79
85
SpelNodeImpl leftOp = getLeftOperand ();
80
86
SpelNodeImpl rightOp = getRightOperand ();
81
- String left = leftOp .getValue (state , String .class );
82
- Object right = rightOp .getValue (state );
83
87
84
- if (left == null ) {
88
+ String input = leftOp .getValue (state , String .class );
89
+ if (input == null ) {
85
90
throw new SpelEvaluationException (leftOp .getStartPosition (),
86
91
SpelMessage .INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR , (Object ) null );
87
92
}
93
+
94
+ Object right = rightOp .getValue (state );
88
95
if (!(right instanceof String )) {
89
96
throw new SpelEvaluationException (rightOp .getStartPosition (),
90
97
SpelMessage .INVALID_SECOND_OPERAND_FOR_MATCHES_OPERATOR , right );
91
98
}
99
+ String regex = (String ) right ;
92
100
93
101
try {
94
- String rightString = (String ) right ;
95
- Pattern pattern = this .patternCache .get (rightString );
102
+ Pattern pattern = this .patternCache .get (regex );
96
103
if (pattern == null ) {
97
- pattern = Pattern .compile (rightString );
98
- this .patternCache .putIfAbsent (rightString , pattern );
104
+ checkRegexLength (regex );
105
+ pattern = Pattern .compile (regex );
106
+ this .patternCache .putIfAbsent (regex , pattern );
99
107
}
100
- Matcher matcher = pattern .matcher (new MatcherInput (left , new AccessCount ()));
108
+ Matcher matcher = pattern .matcher (new MatcherInput (input , new AccessCount ()));
101
109
return BooleanTypedValue .forValue (matcher .matches ());
102
110
}
103
111
catch (PatternSyntaxException ex ) {
@@ -110,6 +118,13 @@ public BooleanTypedValue getValueInternal(ExpressionState state) throws Evaluati
110
118
}
111
119
}
112
120
121
+ private void checkRegexLength (String regex ) {
122
+ if (regex .length () > MAX_REGEX_LENGTH ) {
123
+ throw new SpelEvaluationException (getStartPosition (),
124
+ SpelMessage .MAX_REGEX_LENGTH_EXCEEDED , MAX_REGEX_LENGTH );
125
+ }
126
+ }
127
+
113
128
114
129
private static class AccessCount {
115
130
@@ -127,7 +142,7 @@ private static class MatcherInput implements CharSequence {
127
142
128
143
private final CharSequence value ;
129
144
130
- private AccessCount access ;
145
+ private final AccessCount access ;
131
146
132
147
public MatcherInput (CharSequence value , AccessCount access ) {
133
148
this .value = value ;
0 commit comments