Skip to content

Commit 8bee547

Browse files
committed
fix(core): escape brackets and whitespace to prevent runtime regex crashes
Resolved two critical escaping flaws in RegexEscaper that caused runtime failures: - Added '[' to inside-bracket escaping to prevent 'Unclosed character class' PatternSyntaxException. - Added space (' ') and hash ('#') to general escaping to safely support the COMMENTS (?x) global flag. - Updated assertions in affected unit tests to reflect the new, safer escaped string outputs.
1 parent 80f66dc commit 8bee547

File tree

3 files changed

+8
-7
lines changed

3 files changed

+8
-7
lines changed

sift-core/src/main/java/com/mirkoddd/sift/core/RegexEscaper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ final class RegexEscaper {
2424
private static final boolean[] SPECIAL_CHAR_TABLE = new boolean[128];
2525

2626
static {
27-
String specialChars = ".?*+^$[](){}|\\<>=!";
27+
String specialChars = ".?*+^$[](){}|\\<>=! #";
2828
for (char c : specialChars.toCharArray()) {
2929
SPECIAL_CHAR_TABLE[c] = true;
3030
}
@@ -67,6 +67,7 @@ static void escapeInsideBrackets(char c, StringBuilder sb) {
6767
case '-':
6868
case '^':
6969
case ']':
70+
case '[':
7071
case '&': // Safety against "&&" (intersection)
7172
sb.append('\\');
7273
break;

sift-core/src/test/java/com/mirkoddd/sift/core/RegexEscaperTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,19 @@ void testEscapeString_NormalCharactersAreNotEscaped() {
5555

5656
RegexEscaper.escapeString(normalText, sb);
5757

58-
assertEquals("abc123 ", sb.toString());
58+
assertEquals("abc123\\ ", sb.toString());
5959
}
6060

6161
@Test
6262
void testEscapeInsideBrackets_HitsAllSpecialCharacters() {
63-
char[] bracketSpecials = {'\\', '-', '^', ']', '&'};
63+
char[] bracketSpecials = {'\\', '-', '^', ']', '[', '&'};
6464
StringBuilder sb = new StringBuilder();
6565

6666
for (char c : bracketSpecials) {
6767
RegexEscaper.escapeInsideBrackets(c, sb);
6868
}
6969

70-
assertEquals("\\\\\\-\\^\\]\\&", sb.toString());
70+
assertEquals("\\\\\\-\\^\\]\\[\\&", sb.toString());
7171
}
7272

7373
@Test
@@ -86,6 +86,6 @@ void testEscapeInsideBrackets_NormalCharactersAreNotEscaped() {
8686
void literalWithNonAsciiCharacters() {
8787
SiftPattern pattern = SiftPatterns.literal("Caffè €");
8888

89-
assertEquals("Caffè €", pattern.shake());
89+
assertEquals("Caffè\\ €", pattern.shake());
9090
}
9191
}

sift-core/src/test/java/com/mirkoddd/sift/core/SiftTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ void namedCapturing() {
419419
.namedCapture(orderIdGroup)
420420
.shake();
421421

422-
assertEquals("Order: #(?<orderId>[0-9]+)", regex);
422+
assertEquals("Order:\\ \\#(?<orderId>[0-9]+)", regex);
423423

424424
Matcher m = Pattern.compile(regex).matcher("Status for Order: #9988");
425425
assertTrue(m.find());
@@ -1019,7 +1019,7 @@ void positiveLookbehindTest() {
10191019
.pattern(literal("apple"))
10201020
.shake();
10211021

1022-
assertEquals("(?<=green )apple", regex);
1022+
assertEquals("(?<=green\\ )apple", regex);
10231023
assertRegexMatches(regex, "I like my green apple.");
10241024
assertRegexDoesNotMatch(regex, "I like my red apple.");
10251025
}

0 commit comments

Comments
 (0)