Avoid too many character access attempts in AntPathMatcher

Closes gh-36799
This commit is contained in:
Sam Brannen
2026-05-11 11:51:31 +02:00
committed by Brian Clozel
parent e8f10244e3
commit 12b44f2545
@@ -723,7 +723,7 @@ public class AntPathMatcher implements PathMatcher {
return this.caseSensitive ? this.rawPattern.equals(str) : this.rawPattern.equalsIgnoreCase(str);
}
else if (this.pattern != null) {
Matcher matcher = this.pattern.matcher(str);
Matcher matcher = this.pattern.matcher(new MaxAttemptsCharSequence(str));
if (matcher.matches()) {
if (uriTemplateVariables != null) {
if (this.variableNames.size() != matcher.groupCount()) {
@@ -748,6 +748,60 @@ public class AntPathMatcher implements PathMatcher {
return false;
}
private static class MaxAttemptsCharSequence implements CharSequence {
private static final int MAX_ATTEMPTS = 1_000_000;
private final String text;
private final Counter counter;
MaxAttemptsCharSequence(String text) {
this(text, new Counter());
}
private MaxAttemptsCharSequence(String text, Counter counter) {
this.text = text;
this.counter = counter;
}
@Override
public int length() {
return this.text.length();
}
@Override
public char charAt(int index) {
if (this.counter.value++ >= MAX_ATTEMPTS) {
throw new IllegalStateException(
"Too many character access attempts encountered during pattern matching");
}
return this.text.charAt(index);
}
@Override
public boolean isEmpty() {
return this.text.isEmpty();
}
@Override
public CharSequence subSequence(int start, int end) {
return new MaxAttemptsCharSequence(this.text.substring(start, end), this.counter);
}
@Override
public String toString() {
return this.text;
}
private static class Counter {
private int value;
}
}
}