StackOverflow Error using sonar-java-plugin-5.13.0 on variable reassigment

Plugin fails with StackOverflowError when encountering code that reassigns variables

Version: sonar-java-plugin-5.13.0

Error:

java.lang.StackOverflowError: null
	at org.sonar.java.model.JavaTree.is(JavaTree.java:106)
	at org.sonar.java.checks.helpers.ReassignmentFinder.checkAssignment(ReassignmentFinder.java:97)
	at org.sonar.java.checks.helpers.ReassignmentFinder.getReassignments(ReassignmentFinder.java:86)
	at org.sonar.java.checks.helpers.ExpressionsHelper.getSingleWriteUsage(ExpressionsHelper.java:115)
	at org.sonar.java.checks.helpers.ExpressionsHelper.valueResolution(ExpressionsHelper.java:100)
	at org.sonar.java.checks.helpers.ExpressionsHelper.valueResolution(ExpressionsHelper.java:105)

Steps to reproduce:

ExpressionHelperTest.java

      @Test
      public void switchValueAssignment() {
        String code = newCode("String foo(String a, String b) {",
                              "String c = a;",
                              "a = b;",
                              "b = c;",
                              "return a;}");

    assertValueResolution(code, null);

Potential fix:
In ExpressionHelper.java change the value resolution to track the previous parents to prevent problem

      public static ValueResolution getConstantValue(ExpressionTree expression) {
        return valueResolution(expression, ConstantUtils::resolveAsConstant, new ValueResolution<>(), null);
      }

      public static ValueResolution<String> getConstantValueAsString(ExpressionTree expression) {
        return valueResolution(expression, ConstantUtils::resolveAsStringConstant, new ValueResolution<>(), null);
      }

      public static ValueResolution<Boolean> getConstantValueAsBoolean(ExpressionTree expression) {
        return valueResolution(expression, ConstantUtils::resolveAsBooleanConstant, new ValueResolution<>(), null);
      }

      private static <T> ValueResolution<T> valueResolution(ExpressionTree expression, Function<ExpressionTree,T> resolver, ValueResolution<T> valueResolution,
              List<Object> parents) {

        T value = resolver.apply(expression);
        if (value == null && expression.is(Tree.Kind.IDENTIFIER)) {

          ExpressionTree singleWriteUsage = getSingleWriteUsage(((IdentifierTree) expression).symbol());
          if ((singleWriteUsage == null || !isStrictAssignmentOrDeclaration(singleWriteUsage) || singleWriteUsage == expression) ||
              (parents != null && parents.contains(singleWriteUsage))) {
            value = null;
          } else {
            if (parents == null) {
              parents = new ArrayList<>();
            }
            parents.add(expression);
            valueResolution.addLocation(singleWriteUsage);
            return valueResolution(singleWriteUsage, resolver, valueResolution, parents);
          }
        }
        valueResolution.value = value;
        return valueResolution;
      }
2 Likes

I confirm the problem, @dgriff thanks for reporting this. I created the ticket SONARJAVA-3117 and we will do bugfix release 5.13.1 to fix it.

2 Likes