Skip to content

Commit 99cfe86

Browse files
committed
[fix]stackoverflow occurred when very long horizotal line
1 parent 3239a35 commit 99cfe86

1 file changed

Lines changed: 48 additions & 3 deletions

File tree

flexmark/src/main/java/com/vladsch/flexmark/parser/core/ThematicBreakParser.java

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,56 @@
1212
import java.util.Arrays;
1313
import java.util.HashSet;
1414
import java.util.Set;
15-
import java.util.regex.Pattern;
1615

1716
public class ThematicBreakParser extends AbstractBlockParser {
1817

19-
static Pattern PATTERN = Pattern.compile("^(?:(?:\\*[ \t]*){3,}|(?:_[ \t]*){3,}|(?:-[ \t]*){3,})[ \t]*$");
18+
/**
19+
* Checks if the given input matches the thematic break pattern without using regex
20+
* to avoid StackOverflowError with very long sequences.
21+
*
22+
* Pattern: ^(?:(?:\*[ \t]*){3,}|(?:_[ \t]*){3,}|(?:-[ \t]*){3,})[ \t]*$
23+
* - At least 3 occurrences of *, _, or - characters
24+
* - Characters can be separated by spaces or tabs
25+
* - Only one type of character allowed per line
26+
* - Line can end with spaces or tabs
27+
*/
28+
private static boolean matchesThematicBreak(BasedSequence input) {
29+
int length = input.length();
30+
if (length == 0) return false;
31+
32+
// Skip leading whitespace
33+
int pos = 0;
34+
while (pos < length && isWhitespace(input.charAt(pos))) {
35+
pos++;
36+
}
37+
38+
if (pos >= length) return false;
39+
40+
char patternChar = input.charAt(pos);
41+
if (patternChar != '*' && patternChar != '_' && patternChar != '-') {
42+
return false;
43+
}
44+
45+
int charCount = 0;
46+
while (pos < length) {
47+
char c = input.charAt(pos);
48+
if (c == patternChar) {
49+
charCount++;
50+
} else if (isWhitespace(c)) {
51+
// Whitespace is allowed between pattern characters
52+
} else {
53+
// Invalid character found
54+
return false;
55+
}
56+
pos++;
57+
}
58+
59+
return charCount >= 3;
60+
}
61+
62+
private static boolean isWhitespace(char c) {
63+
return c == ' ' || c == '\t';
64+
}
2065

2166
final private ThematicBreak block = new ThematicBreak();
2267

@@ -96,7 +141,7 @@ public BlockStart tryStart(ParserState state, MatchedBlockParser matchedBlockPar
96141
}
97142
BasedSequence line = state.getLine();
98143
final BasedSequence input = line.subSequence(state.getNextNonSpaceIndex(), line.length());
99-
if (PATTERN.matcher(input).matches()) {
144+
if (matchesThematicBreak(input)) {
100145
return BlockStart.of(new ThematicBreakParser(line.subSequence(state.getIndex()))).atIndex(line.length());
101146
} else {
102147
return BlockStart.none();

0 commit comments

Comments
 (0)