diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index b8f8783555..c2ba2e8b10 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,9 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +* java + * [#3117](https://github.com/pmd/pmd/issues/3117): \[java] Infinite loop when parsing invalid code nested in lambdas + ### API Changes ### External Contributions diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 43eaed8593..be6a803151 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -237,6 +237,11 @@ options { TRACK_TOKENS = true; NODE_PACKAGE="net.sourceforge.pmd.lang.java.ast"; + // disable the calculation of expected tokens when a parse error occurs + // depending on the possible allowed next tokens, this + // could be expensive (see https://github.com/pmd/pmd/issues/3117) + //ERROR_REPORTING = false; + //DEBUG_PARSER = true; //DEBUG_LOOKAHEAD = true; //DEBUG_TOKEN_MANAGER = true; @@ -2131,9 +2136,9 @@ void StatementExpression() : | PreDecrementExpression() | - LOOKAHEAD( PrimaryExpression() AssignmentOperator() ) PrimaryExpression() AssignmentOperator() Expression() -| - PostfixExpression() + // using PostfixExpression here allows us to skip the part of the production tree + // between Expression() and PostfixExpression() + PostfixExpression() [ AssignmentOperator() Expression() ] } void SwitchStatement(): diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java index 16f1c4786b..f545446d84 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java @@ -226,6 +226,13 @@ public class ParserCornersTest { java8.parseResource("GitHubBug309.java"); } + @Test(timeout = 30000) + public void testInfiniteLoopInLookahead() { + expect.expect(ParseException.class); + // https://github.com/pmd/pmd/issues/3117 + java8.parseResource("InfiniteLoopInLookahead.java"); + } + /** * This triggered bug #1484 UnusedLocalVariable - false positive - * parenthesis diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/InfiniteLoopInLookahead.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/InfiniteLoopInLookahead.java new file mode 100644 index 0000000000..55552bd48a --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/InfiniteLoopInLookahead.java @@ -0,0 +1,28 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +import java.util.*; + +public class InfiniteLoopInLookahead { + + public void exam1(List resList) { + resList.forEach(a -> { + resList.forEach(b -> { + resList.forEach(c -> { + resList.forEach(d -> { + resList.forEach(e -> { + resList.forEach(f -> { + resList.forEach(g -> { + resList.forEach(h -> { + resList // note: missing semicolon -> parse error here... + }); + }); + }); + }); + }); + }); + }); + }); + } +}