Skip to content

Commit fe3ef71

Browse files
authored
Wrap "Pattern too complex" exception into an IllegalArgumentException (#109173) (#109255)
1 parent c2b4093 commit fe3ef71

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

docs/changelog/109173.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 109173
2+
summary: Wrap "Pattern too complex" exception into an `IllegalArgumentException`
3+
area: Mapping
4+
type: bug
5+
issues: []

modules/analysis-common/src/yamlRestTest/resources/rest-api-spec/test/analysis-common/50_char_filters.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,33 @@
2727
- length: { tokens: 1 }
2828
- match: { tokens.0.token: "replacedSample 6 sample1" }
2929

30+
---
31+
"pattern_replace error handling (too complex pattern)":
32+
- do:
33+
catch: bad_request
34+
indices.create:
35+
index: test_too_complex_regex_pattern
36+
body:
37+
settings:
38+
index:
39+
analysis:
40+
analyzer:
41+
my_analyzer:
42+
tokenizer: standard
43+
char_filter:
44+
- my_char_filter
45+
char_filter:
46+
my_char_filter:
47+
type: "pattern_replace"
48+
# This pattern intentionally uses special characters designed to throw an error.
49+
# It's expected that the pattern may not render correctly.
50+
pattern: "(\\d+)-(?=\\d\nͭͭͭͭͭͭͭͭͭͭͭͭͭͭͭ"
51+
flags: CASE_INSENSITIVE|MULTILINE|DOTALL|UNICODE_CASE|CANON_EQ
52+
replacement: "_$1"
53+
- match: { status: 400 }
54+
- match: { error.type: illegal_argument_exception }
55+
- match: { error.reason: "Too complex regex pattern" }
56+
3057
---
3158
"mapping":
3259
- do:

server/src/main/java/org/elasticsearch/common/regex/Regex.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,26 @@ public static boolean simpleMatch(final List<String> patterns, final String str)
230230
}
231231

232232
public static Pattern compile(String regex, String flags) {
233-
int pFlags = flags == null ? 0 : flagsFromString(flags);
234-
return Pattern.compile(regex, pFlags);
233+
try {
234+
int pFlags = flags == null ? 0 : flagsFromString(flags);
235+
return Pattern.compile(regex, pFlags);
236+
} catch (OutOfMemoryError e) {
237+
if (e.getMessage().equals("Pattern too complex")) {
238+
// Normally, we do try to handle OutOfMemoryError errors, as they typically indicate the JVM is not healthy.
239+
//
240+
// In the context of Pattern::compile, an OutOfMemoryError can occur if the pattern is too complex.
241+
// In this case, the OutOfMemoryError is thrown by a pre-check rather than actual memory exhaustion.
242+
//
243+
// Because the JVM has not encountered a real memory issue, we can treat this as a recoverable exception by wrapping
244+
// the original OutOfMemoryError in an IllegalArgumentException.
245+
//
246+
// For additional details, see:
247+
// - https://bugs.openjdk.org/browse/JDK-8300207
248+
// - https://github.com/openjdk/jdk/commit/030b071db1fb6197a2633a04b20aa95432a903bc
249+
throw new IllegalArgumentException("Too complex regex pattern", e);
250+
}
251+
throw e;
252+
}
235253
}
236254

237255
public static int flagsFromString(String flags) {

0 commit comments

Comments
 (0)