]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3708 Improve exception message from CodeReader in case of StackOverflowError
authorEvgeny Mandrikov <mandrikov@gmail.com>
Thu, 27 Sep 2012 16:38:42 +0000 (20:38 +0400)
committerEvgeny Mandrikov <mandrikov@gmail.com>
Thu, 27 Sep 2012 17:27:25 +0000 (21:27 +0400)
sonar-channel/src/main/java/org/sonar/channel/CodeReader.java
sonar-channel/src/main/java/org/sonar/channel/RegexChannel.java
sonar-channel/src/test/java/org/sonar/channel/CodeReaderTest.java

index f1f85e8f20628a3b4996d351c76ce52fd306fceb..4ca2328186e619ee6dd58aa037b71ac439eeeffc 100644 (file)
@@ -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) {
index 1272c0be5421aebf2517cf5ce1df8f6c8187a6bb..145230f1473fdd064f95345ed14f80f93e0f1b4f 100644 (file)
@@ -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);
+
 }
index f0cd762825a2972fa1c3fd990b4ba09511477be7..d52ae92b2aaf34980bcdfb68be474e3e6557a736 100644 (file)
  */
 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;");
@@ -95,6 +100,24 @@ public class CodeReaderTest {
     assertEquals( -1, reader.popTo(Pattern.compile("\\w+").matcher(new String()), token));
   }
 
+  @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());