aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-channel
diff options
context:
space:
mode:
authorEvgeny Mandrikov <mandrikov@gmail.com>2012-09-27 20:38:42 +0400
committerEvgeny Mandrikov <mandrikov@gmail.com>2012-09-27 21:27:25 +0400
commit2eb10e0f6089eed0d4cd3483f350db30a34c5cb6 (patch)
treea430dfda16164721df8bcdd7b821b9312a93d4e7 /sonar-channel
parent54a9cb8008efb89cfd6d85a9e8bde79e0c7a0518 (diff)
downloadsonarqube-2eb10e0f6089eed0d4cd3483f350db30a34c5cb6.tar.gz
sonarqube-2eb10e0f6089eed0d4cd3483f350db30a34c5cb6.zip
SONAR-3708 Improve exception message from CodeReader in case of StackOverflowError
Diffstat (limited to 'sonar-channel')
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/CodeReader.java25
-rw-r--r--sonar-channel/src/main/java/org/sonar/channel/RegexChannel.java26
-rw-r--r--sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java31
3 files changed, 50 insertions, 32 deletions
diff --git a/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java b/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java
index f1f85e8f206..4ca2328186e 100644
--- a/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java
+++ b/sonar-channel/src/main/java/org/sonar/channel/CodeReader.java
@@ -48,7 +48,7 @@ public class CodeReader extends CodeBuffer {
/**
* Creates a code reader with specific configuration parameters.
* Note that this constructor will read everything from reader and will close it.
- *
+ *
* @param code
* the Reader to read code from
* @param configuration
@@ -60,7 +60,7 @@ public class CodeReader extends CodeBuffer {
/**
* Creates a code reader with specific configuration parameters.
- *
+ *
* @param code
* the code itself
* @param configuration
@@ -72,7 +72,7 @@ public class CodeReader extends CodeBuffer {
/**
* Read and consume the next character
- *
+ *
* @param appendable
* the read character is appended to appendable
*/
@@ -86,7 +86,7 @@ public class CodeReader extends CodeBuffer {
/**
* Read without consuming the next characters
- *
+ *
* @param length
* number of character to read
* @return array of characters
@@ -104,7 +104,7 @@ public class CodeReader extends CodeBuffer {
/**
* Read without consuming the next characters until a condition is reached (EndMatcher)
- *
+ *
* @param matcher
* the EndMatcher used to stop the reading
* @param appendable
@@ -114,7 +114,7 @@ public class CodeReader extends CodeBuffer {
int index = 0;
char nextChar = charAt(index);
try {
- while ( !matcher.match(nextChar) && nextChar != -1) {
+ while (!matcher.match(nextChar) && nextChar != -1) {
appendable.append(nextChar);
nextChar = charAt(++index);
}
@@ -142,7 +142,7 @@ public class CodeReader extends CodeBuffer {
try {
do {
appendable.append((char) pop());
- } while ( !matcher.match(peek()) && peek() != -1);
+ } while (!matcher.match(peek()) && peek() != -1);
} catch (IOException e) {
throw new ChannelException(e.getMessage(), e);
}
@@ -150,7 +150,7 @@ public class CodeReader extends CodeBuffer {
/**
* Read and consume the next characters according to a given regular expression
- *
+ *
* @param matcher
* the regular expression matcher
* @param appendable
@@ -164,7 +164,7 @@ public class CodeReader extends CodeBuffer {
/**
* Read and consume the next characters according to a given regular expression. Moreover the character sequence immediately following the
* desired characters must also match a given regular expression.
- *
+ *
* @param matcher
* the Matcher used to try consuming next characters
* @param afterMatcher
@@ -180,7 +180,7 @@ public class CodeReader extends CodeBuffer {
if (afterMatcher != null) {
afterMatcher.reset(this);
afterMatcher.region(matcher.end(), length());
- if ( !afterMatcher.lookingAt()) {
+ if (!afterMatcher.lookingAt()) {
return -1;
}
}
@@ -190,6 +190,11 @@ public class CodeReader extends CodeBuffer {
}
return matcher.end();
}
+ } catch (StackOverflowError e) {
+ throw new ChannelException("Unable to apply regular expression '" + matcher.pattern().pattern()
+ + "' at line " + getCursor().getLine() + " and column " + getCursor().getColumn()
+ + ", because it led to a stack overflow error."
+ + " This error may be due to an inefficient use of alternations - see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5050507");
} catch (IndexOutOfBoundsException e) {
return -1;
} catch (IOException e) {
diff --git a/sonar-channel/src/main/java/org/sonar/channel/RegexChannel.java b/sonar-channel/src/main/java/org/sonar/channel/RegexChannel.java
index 1272c0be542..145230f1473 100644
--- a/sonar-channel/src/main/java/org/sonar/channel/RegexChannel.java
+++ b/sonar-channel/src/main/java/org/sonar/channel/RegexChannel.java
@@ -29,46 +29,36 @@ public abstract class RegexChannel<OUTPUT> extends Channel<OUTPUT> {
private final StringBuilder tmpBuilder = new StringBuilder();
private final Matcher matcher;
- private final String regex;
/**
* Create a RegexChannel object with the required regular expression
- *
+ *
* @param regex
* regular expression to be used to try matching the next characters in the stream
*/
public RegexChannel(String regex) {
matcher = Pattern.compile(regex).matcher("");
- this.regex = regex;
}
@Override
public final boolean consume(CodeReader code, OUTPUT output) {
- try {
- if (code.popTo(matcher, tmpBuilder) > 0) {
- consume(tmpBuilder, output);
- tmpBuilder.delete(0, tmpBuilder.length());
- return true;
- }
- return false;
- } catch (StackOverflowError e) {
- throw new IllegalArgumentException(
- "The regular expression "
- + regex
- + " has led to a stack overflow error. "
- + "This error is certainly due to an inefficient use of alternations. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5050507",
- e);
+ if (code.popTo(matcher, tmpBuilder) > 0) {
+ consume(tmpBuilder, output);
+ tmpBuilder.delete(0, tmpBuilder.length());
+ return true;
}
+ return false;
}
/**
* The consume method is called each time the regular expression used to create the RegexChannel object matches the next characters in the
* character streams.
- *
+ *
* @param token
* the token consumed in the character stream and matching the regular expression
* @param the
* OUPUT object which can be optionally fed
*/
protected abstract void consume(CharSequence token, OUTPUT output);
+
}
diff --git a/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java b/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java
index f0cd762825a..d52ae92b2aa 100644
--- a/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java
+++ b/sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java
@@ -19,18 +19,23 @@
*/
package org.sonar.channel;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
import java.io.StringReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.junit.Test;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
public class CodeReaderTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
@Test
public void testPopWithAppendable() {
CodeReader reader = new CodeReader("package org.sonar;");
@@ -96,6 +101,24 @@ public class CodeReaderTest {
}
@Test
+ public void test() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("\n");
+ for (int i = 0; i < 10000; i++) {
+ sb.append(Integer.toHexString(i));
+ }
+ CodeReader reader = new CodeReader(sb.toString());
+ reader.pop();
+ reader.pop();
+
+ thrown.expect(ChannelException.class);
+ thrown.expectMessage("Unable to apply regular expression '([a-fA-F]|\\d)+' at line 2 and column 1," +
+ " because it led to a stack overflow error." +
+ " This error may be due to an inefficient use of alternations - see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5050507");
+ reader.popTo(Pattern.compile("([a-fA-F]|\\d)+").matcher(""), new StringBuilder());
+ }
+
+ @Test
public void testPopToWithRegexAndFollowingMatcher() {
Matcher digitMatcher = Pattern.compile("\\d+").matcher(new String());
Matcher alphabeticMatcher = Pattern.compile("[a-zA-Z]").matcher(new String());