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;
}