java.lang.StackOverflowError: null in org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan

Hi sonarqube support,
We are using: sonarqube v7.4.0 with the following plugins:
SonarQube plugins:

  • Findbugs 3.9.1 (findbugs)
  • SonarPython 1.10.0.2131 (python)
  • SonarJava 5.9.2.16552 (java)
  • LDAP 2.2.0.608 (ldap)
  • Git 1.6.0.1349 (scmgit)
  • PMD 3.1.3 (pmd)
  • SonarGo 1.1.0.1612 (go)
  • SonarPHP 2.15.0.4060 (php)
  • SonarTS 1.8.0.3332 (typescript)
  • SonarJS 5.0.0.6962 (javascript)
  • SVG Badges 3.0.1 (status)

Using the maven scanner: sonar-maven-plugin:3.5.0.1254:sonarsonar-maven-plugin:3.5.0.1254:sonar
the following error can be seen:

[ERROR] A stack overflow error occured while analyzing file: .../service/UploadServlet.java
java.lang.StackOverflowError: null
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:33)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.visitMemberSelectExpression(BaseTreeVisitor.java:227)
	at org.sonar.java.model.expression.MemberSelectExpressionTreeImpl.accept(MemberSelectExpressionTreeImpl.java:115)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:40)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.visitMethodInvocation(BaseTreeVisitor.java:250)
	at org.sonar.java.checks.AbstractInjectionChecker$LocalVariableDynamicStringVisitor.visitMethodInvocation(AbstractInjectionChecker.java:150)
	at org.sonar.java.model.expression.MethodInvocationTreeImpl.accept(MethodInvocationTreeImpl.java:96)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:40)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.visitAssignmentExpression(BaseTreeVisitor.java:275)
	at org.sonar.java.checks.AbstractInjectionChecker$LocalVariableDynamicStringVisitor.visitAssignmentExpression(AbstractInjectionChecker.java:141)
	at org.sonar.java.model.expression.AssignmentExpressionTreeImpl.accept(AssignmentExpressionTreeImpl.java:71)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:40)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.visitExpressionStatement(BaseTreeVisitor.java:101)
	at org.sonar.java.model.statement.ExpressionStatementTreeImpl.accept(ExpressionStatementTreeImpl.java:65)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:40)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:34)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.visitBlock(BaseTreeVisitor.java:85)
	at org.sonar.java.model.statement.BlockTreeImpl.accept(BlockTreeImpl.java:77)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:40)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.visitIfStatement(BaseTreeVisitor.java:108)
	at org.sonar.java.model.statement.IfStatementTreeImpl.accept(IfStatementTreeImpl.java:124)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:40)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:34)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.visitBlock(BaseTreeVisitor.java:85)
	at org.sonar.java.model.statement.BlockTreeImpl.accept(BlockTreeImpl.java:77)
	at org.sonar.java.checks.AbstractInjectionChecker.isIdentifierDynamicString(AbstractInjectionChecker.java:103)
	at org.sonar.java.checks.AbstractInjectionChecker.isDynamicString(AbstractInjectionChecker.java:72)
	at org.sonar.java.checks.AbstractInjectionChecker.isDynamicString(AbstractInjectionChecker.java:60)
	at org.sonar.java.checks.AbstractInjectionChecker.isDynamicString(AbstractInjectionChecker.java:75)
	at org.sonar.java.checks.AbstractInjectionChecker.isDynamicString(AbstractInjectionChecker.java:60)
	at org.sonar.java.checks.AbstractInjectionChecker$LocalVariableDynamicStringVisitor.visitAssignmentExpression(AbstractInjectionChecker.java:139)
	at org.sonar.java.model.expression.AssignmentExpressionTreeImpl.accept(AssignmentExpressionTreeImpl.java:71)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:40)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.visitExpressionStatement(BaseTreeVisitor.java:101)
	at org.sonar.java.model.statement.ExpressionStatementTreeImpl.accept(ExpressionStatementTreeImpl.java:65)
	at org.sonar.plugins.java.api.tree.BaseTreeVisitor.scan(BaseTreeVisitor.java:40)
….

Thanks,
Stoyan

Hello Stoyan,

The issue is coming from SonarJava plugin (that’s for sure), and most probably from rule squid:S2077 (Executing SQL queries is security-sensitive).

You can try to temporarily disable the rule and see if the analysis stops failing.

If it’s the case, I would really appreciate if you could try to identify - first - the code snippet in the given class which makes the analysis fail, and - second- if you could try to manually craft a simple self-contained reproducer which reproduce the issue systematically, without the need of any external dependency. Without this, I won’t be able to identify the issue in the rule.

Cheers,
Michael

Edit:

Note that we are not commercial support here, but on the Community forum. As SonarSourcers, we are trying to help our community, on a best effort basis. If you are using a commercial edition, please directly contact commercial support.

Thanks Michael,

Analysis have stopped to fail when the mentioned rule was disabled.

All the best,
Stoyan

A StackOverflowError is simply signals that there is no more memory available. It is to the stack what an OutOfMemoryError is to the heap: it simply signals that there is no more memory available. JVM has a given memory allocated for each stack of each thread, and if an attempt to call a method happens to fill this memory, JVM throws an error. Just like it would do if you were trying to write at index N of an array of length N. No memory corruption can happen. The stack can not write into the heap.

The common cause for a stackoverflow is a bad recursive call. Typically, this is caused when your recursive functions doesn’t have the correct termination condition, so it ends up calling itself forever. Or when the termination condition is fine, it can be caused by requiring too many recursive calls before fulfilling it.

Here’s an example:

public class Overflow {
    public static final void main(String[] args) {
        main(args);
    }
}

That function calls itself repeatedly with no termination condition. Consequently, the stack fills up because each call has to push a return address on the stack, but the return addresses are never popped off the stack because the function never returns, it just keeps calling itself.

Thank you for the details about WHAT is a stackoverflow, @fillermark… Note that this is unfortunately completely out of scope of this thread, as the SOF is/was precisely caused by the implementation of a rule. The static analysis engine itself loop.