Bug Report: (Java) Control-flow branching statements (break/continue) consistently cause exceptions in SonarJava 4.14

61 views
Skip to first unread message

mike...@gmail.com

unread,
Oct 6, 2017, 4:43:24 PM10/6/17
to SonarQube
Hello,

SonarQube analysis consistently fails with an IllegalStateException when control-flow branching statements are used within a try-catch clause inside of a loop.

This is a blocking issue for us and is preventing us from upgrading to SonarJava 4.14. We are currently running SonarJava 4.8 and not experiencing the issue, but we would like to update for all of the new rules and enhancements as soon as possible.

I'm not very familiar with how SonarQube works behind-the-scenes, but this appears to be related to parsing when running SECheck classes. On our actual codebase, we are consistently getting an IndexOutOfBoundsException in DivisionByZeroCheck. In an effort to produce as small of an MCV as possible I've narrowed it to a case that produces an IllegalStateException instead.

Environment:
  • SonarQube: 5.6.4 (LTS)
  • SonarJava: 4.14.0.11784
  • Local JRE version: 1.8.0_102
  • Runner: org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.5

Minimal, complete, and verifiable example:
  • Enable the SonarQube Java rule squid:S2222 ("Locks should be released")
    • Other rules extending SECheck seem to cause the issue as well, such as squid:S2583 ("Conditionally executed blocks should be reachable")
  • Run an analysis on the following file (McvExample.java):

    public class McvExample {
        public void run() {
            for (int i = 0; i < 1; i++) { // The same issue is also triggered with a "while" loop
                try {
                    continue; // SQ analysis fails if this is either "continue" or "break   "
                }
                finally {
                    System.out.println(true ? "" : ""); // This is required; I suspect that it somehow triggers the rule to be run
                }
            }
        }
    }

    Example gradle.build:
    apply plugin: 'org.sonarqube'

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.5'
        }
    }

    Example Gradle command execution:
    gradle :sonarqube '-Dsonar.host.url=http://sonarqube/'-Dsonar.login=admin' '-Dsonar.password=admin' '-Dsonar.sources=src/java/MvcExample.java' --stacktrace

  • The analysis fails to complete and the following stack trace appears (Gradle block of stack trace omitted for brevity):

    Caused by: org.sonar.squidbridge.api.AnalysisException: SonarQube is unable to analyze file : 'C:\sample\src\java\MvcExample.java'
            at org.sonar.java.ast.JavaAstScanner.simpleScan(JavaAstScanner.java:105)
            at org.sonar.java.ast.JavaAstScanner.scan(JavaAstScanner.java:68)
            at org.sonar.java.JavaSquid.scanSources(JavaSquid.java:119)
            at org.sonar.java.JavaSquid.scan(JavaSquid.java:113)
            at org.sonar.plugins.java.JavaSquidSensor.execute(JavaSquidSensor.java:84)
            at org.sonar.batch.sensor.SensorWrapper.analyse(SensorWrapper.java:57)
            at org.sonar.batch.phases.SensorsExecutor.executeSensor(SensorsExecutor.java:58)
            at org.sonar.batch.phases.SensorsExecutor.execute(SensorsExecutor.java:50)
            at org.sonar.batch.phases.AbstractPhaseExecutor.execute(AbstractPhaseExecutor.java:83)
            at org.sonar.batch.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:192)
            at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:142)
            at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:127)
            at org.sonar.batch.scan.ProjectScanContainer.scan(ProjectScanContainer.java:241)
            at org.sonar.batch.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:236)
            at org.sonar.batch.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:226)
            at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:142)
            at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:127)
            at org.sonar.batch.task.ScanTask.execute(ScanTask.java:47)
            at org.sonar.batch.task.TaskContainer.doAfterStart(TaskContainer.java:86)
            at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:142)
            at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:127)
            at org.sonar.batch.bootstrap.GlobalContainer.executeTask(GlobalContainer.java:106)
            at org.sonar.batch.bootstrapper.Batch.executeTask(Batch.java:119)
            at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:63)
            at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
            at com.sun.proxy.$Proxy367.execute(Unknown Source)
            at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:233)
            at org.sonarsource.scanner.api.EmbeddedScanner.runAnalysis(EmbeddedScanner.java:151)
            at org.sonarqube.gradle.SonarQubeTask.run(SonarQubeTask.java:99)
            at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
            at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.doExecute(DefaultTaskClassInfoStore.java:141)
            at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:134)
            at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:123)
            at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:632)
            at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:615)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:95)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:76)
            ... 70 more
    Caused by: java.lang.IllegalStateException
            at org.sonar.java.collections.SinglyLinkedList$1.peek(SinglyLinkedList.java:146)
            at org.sonar.java.se.ProgramState.peekValuesAndSymbols(ProgramState.java:242)
            at org.sonar.java.se.ProgramState.peekValues(ProgramState.java:235)
            at org.sonar.java.se.checks.UnclosedResourcesCheck$PreStatementVisitor.closeArguments(UnclosedResourcesCheck.java:418)
            at org.sonar.java.se.checks.UnclosedResourcesCheck$PreStatementVisitor.visitMethodInvocation(UnclosedResourcesCheck.java:391)
            at org.sonar.java.model.expression.MethodInvocationTreeImpl.accept(MethodInvocationTreeImpl.java:96)
            at org.sonar.java.se.checks.UnclosedResourcesCheck.checkPreStatement(UnclosedResourcesCheck.java:137)
            at org.sonar.java.se.CheckerDispatcher.executeCheckPreStatement(CheckerDispatcher.java:54)
            at org.sonar.java.se.ExplodedGraphWalker.visit(ExplodedGraphWalker.java:506)
            at org.sonar.java.se.ExplodedGraphWalker.execute(ExplodedGraphWalker.java:243)
            at org.sonar.java.se.ExplodedGraphWalker.visitMethod(ExplodedGraphWalker.java:203)
            at org.sonar.java.se.ExplodedGraphWalker.visitMethod(ExplodedGraphWalker.java:195)
            at org.sonar.java.se.SymbolicExecutionVisitor.execute(SymbolicExecutionVisitor.java:77)
            at org.sonar.java.se.SymbolicExecutionVisitor.visitNode(SymbolicExecutionVisitor.java:63)
            at org.sonar.java.ast.visitors.SubscriptionVisitor.visit(SubscriptionVisitor.java:95)
            at org.sonar.java.ast.visitors.SubscriptionVisitor.visitChildren(SubscriptionVisitor.java:120)
            at org.sonar.java.ast.visitors.SubscriptionVisitor.visit(SubscriptionVisitor.java:97)
            at org.sonar.java.ast.visitors.SubscriptionVisitor.visitChildren(SubscriptionVisitor.java:120)
            at org.sonar.java.ast.visitors.SubscriptionVisitor.visit(SubscriptionVisitor.java:97)
            at org.sonar.java.ast.visitors.SubscriptionVisitor.scanTree(SubscriptionVisitor.java:78)
            at org.sonar.java.ast.visitors.SubscriptionVisitor.scanFile(SubscriptionVisitor.java:64)
            at org.sonar.java.model.VisitorsBridge.visitFile(VisitorsBridge.java:114)
            at org.sonar.java.ast.JavaAstScanner.simpleScan(JavaAstScanner.java:96)
            ... 106 more

Michael Gumowski

unread,
Oct 9, 2017, 11:24:42 AM10/9/17
to mike...@gmail.com, SonarQube
Hello Mike,

Thanks a lot for the feedback, your investigation and the self-contained reproducer!
I identified the issue and created the following ticket to tackle it: SONARJAVA-2515

I added some technical details in the ticket, but to give you a bit more information, the issue is caused by a wrong CFG generated for the method. All our Symbolic Execution-based rules are relying on the CFG corresponding to the method currently being analyzed. As you rightfully pointed it out, any of these rules can make the analysis fail.
In this very case, the break (or continue) statement is badly branched to last instruction of the finally block. Consequently, while trying to "symbolically" execute the method invocation, our program state ends up, at some point, badly formed (stack not correct), and the engine crashes.

Cheers,
Michael

--
You received this message because you are subscribed to the Google Groups "SonarQube" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sonarqube+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sonarqube/a64a1adf-8105-4844-a774-7fc3347ed7d2%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
Michael Gumowski | SonarSource
Software Developer, Language Team
https://www.sonarsource.com

mike...@gmail.com

unread,
Oct 9, 2017, 4:02:04 PM10/9/17
to SonarQube
Thanks, Michael!

I appreciate the quick and thorough response. I'll watch the ticket and wait for a resolution.

Thanks,
Mike
Reply all
Reply to author
Forward
0 new messages