Skip to content

Commit 48f05b3

Browse files
committed
Fix StringIndexOutOfBoundsException with unclosed inline link (#27)
An example input that caused it: [example.com](http:\\example.com The code was missing a bounds check. By using peek() we get that, as in other places. Also add an integration test that tries to trigger out of bounds by using substrings of the spec examples.
1 parent 12f91cd commit 48f05b3

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package org.commonmark.integration;
2+
3+
import org.commonmark.node.Node;
4+
import org.commonmark.parser.Parser;
5+
import org.commonmark.spec.SpecExample;
6+
import org.commonmark.spec.SpecReader;
7+
import org.junit.Test;
8+
import org.junit.runner.RunWith;
9+
import org.junit.runners.Parameterized;
10+
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
import static org.junit.Assert.assertNotNull;
15+
16+
/**
17+
* Tests various substrings of the spec examples to check for out of bounds exceptions.
18+
*/
19+
@RunWith(Parameterized.class)
20+
public class BoundsIntegrationTest {
21+
22+
private static final Parser PARSER = Parser.builder().build();
23+
24+
protected final String input;
25+
26+
public BoundsIntegrationTest(String input) {
27+
this.input = input;
28+
}
29+
30+
@Parameterized.Parameters(name = "{0}")
31+
public static List<Object[]> data() {
32+
List<SpecExample> examples = SpecReader.readExamples();
33+
List<Object[]> data = new ArrayList<>();
34+
for (SpecExample example : examples) {
35+
data.add(new Object[]{example.getSource()});
36+
}
37+
return data;
38+
}
39+
40+
@Test
41+
public void testSubstrings() {
42+
// Check possibly truncated block/inline starts
43+
for (int i = 1; i < input.length() - 1; i++) {
44+
parse(input.substring(i));
45+
}
46+
// Check possibly truncated block/inline ends
47+
for (int i = input.length() - 1; i > 1; i--) {
48+
parse(input.substring(0, i));
49+
}
50+
}
51+
52+
private void parse(String input) {
53+
try {
54+
Node parsed = PARSER.parse(input);
55+
// Parsing should always return a node
56+
assertNotNull(parsed);
57+
} catch (Exception e) {
58+
throw new AssertionError("Parsing failed, input: " + input, e);
59+
}
60+
}
61+
}

commonmark/src/main/java/org/commonmark/internal/InlineParserImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ private boolean parseCloseBracket() {
570570
title = parseLinkTitle();
571571
spnl();
572572
}
573-
if (input.charAt(index) == ')') {
573+
if (peek() == ')') {
574574
index++;
575575
isLinkOrImage = true;
576576
}

0 commit comments

Comments
 (0)