use of org.sonar.java.se.constraint.ObjectConstraint in project sonar-java by SonarSource.
the class MapComputeIfAbsentOrPresentCheck method checkPreStatement.
@Override
public ProgramState checkPreStatement(CheckerContext context, Tree syntaxNode) {
if (syntaxNode.is(Tree.Kind.METHOD_INVOCATION)) {
MethodInvocationTree mit = (MethodInvocationTree) syntaxNode;
if (MAP_PUT.matches(mit) && !isMethodInvocationThrowingCheckedException(mit.arguments().get(1))) {
ProgramState ps = context.getState();
SymbolicValue keySV = ps.peekValue(1);
SymbolicValue mapSV = ps.peekValue(2);
mapGetInvocations.get(mapSV).stream().filter(getOnSameMap -> getOnSameMap.withSameKey(keySV)).findAny().ifPresent(getOnSameMap -> {
ObjectConstraint constraint = ps.getConstraint(getOnSameMap.value, ObjectConstraint.class);
if (constraint != null && isInsideIfStatementWithNullCheckWithoutElse(mit)) {
checkIssues.add(new CheckIssue(context.getNode(), getOnSameMap.mit, mit, getOnSameMap.value, constraint));
}
});
}
}
return super.checkPreStatement(context, syntaxNode);
}
use of org.sonar.java.se.constraint.ObjectConstraint in project sonar-java by SonarSource.
the class OptionalGetBeforeIsPresentCheck method setOptionalConstraint.
private static List<ProgramState> setOptionalConstraint(CheckerContext context, Tree syntaxNode) {
ProgramState programState = context.getState();
if (!syntaxNode.is(Tree.Kind.METHOD_INVOCATION)) {
return Collections.singletonList(programState);
}
MethodInvocationTree mit = (MethodInvocationTree) syntaxNode;
SymbolicValue peekValue = programState.peekValue();
Preconditions.checkNotNull(peekValue);
if (OPTIONAL_EMPTY.matches(mit)) {
return peekValue.setConstraint(programState, OptionalConstraint.NOT_PRESENT);
}
if (OPTIONAL_OF.matches(mit)) {
return peekValue.setConstraint(programState, OptionalConstraint.PRESENT);
}
if (OPTIONAL_OF_NULLABLE.matches(mit)) {
ProgramState psPriorMethodInvocation = context.getNode().programState;
SymbolicValue paramSV = psPriorMethodInvocation.peekValue(0);
ObjectConstraint paramConstraint = psPriorMethodInvocation.getConstraint(paramSV, ObjectConstraint.class);
if (paramConstraint != null) {
// Optional.ofNullable(null) returns an empty Optional
return peekValue.setConstraint(programState, paramConstraint == ObjectConstraint.NULL ? OptionalConstraint.NOT_PRESENT : OptionalConstraint.PRESENT);
}
}
return Collections.singletonList(programState);
}
use of org.sonar.java.se.constraint.ObjectConstraint in project sonar-java by SonarSource.
the class NullDereferenceCheck method checkConstraint.
private ProgramState checkConstraint(CheckerContext context, Tree syntaxNode, SymbolicValue currentVal) {
ProgramState programState = context.getState();
ObjectConstraint constraint = programState.getConstraint(currentVal, ObjectConstraint.class);
if (constraint != null && constraint.isNull()) {
NullDereferenceIssue issue = new NullDereferenceIssue(context.getNode(), currentVal, syntaxNode);
detectedIssues.peek().add(issue);
// we reported the issue and stopped the exploration, but we still need to create a yield for x-procedural calls
context.addExceptionalYield(currentVal, programState, JAVA_LANG_NPE, this);
return null;
}
constraint = programState.getConstraint(currentVal, ObjectConstraint.class);
if (constraint == null) {
// a NPE will be triggered if the current value would have been null
context.addExceptionalYield(currentVal, programState.addConstraint(currentVal, ObjectConstraint.NULL), JAVA_LANG_NPE, this);
// We dereferenced the target value for the member select, so we can assume it is not null when not already known
return programState.addConstraint(currentVal, ObjectConstraint.NOT_NULL);
}
return programState;
}
use of org.sonar.java.se.constraint.ObjectConstraint in project sonar-java by SonarSource.
the class BytecodeEGWalkerTest method generateMethodBehavior.
@Test
public void generateMethodBehavior() throws Exception {
MethodBehavior methodBehavior = getMethodBehavior("fun(ZLjava/lang/Object;)Ljava/lang/Object;");
assertThat(methodBehavior.yields()).hasSize(2);
SymbolicValue svFirstArg = new SymbolicValue();
SymbolicValue svsecondArg = new SymbolicValue();
SymbolicValue svResult = new SymbolicValue();
List<SymbolicValue> invocationArguments = Lists.newArrayList(svFirstArg, svsecondArg);
List<ObjectConstraint> collect = methodBehavior.yields().stream().map(my -> {
Collection<ProgramState> ps = my.statesAfterInvocation(invocationArguments, Lists.newArrayList(), ProgramState.EMPTY_STATE, () -> svResult).collect(Collectors.toList());
assertThat(ps).hasSize(1);
ProgramState next = ps.iterator().next();
return next.getConstraint(svResult, ObjectConstraint.class);
}).collect(Collectors.toList());
assertThat(collect).hasSize(2).containsOnly(ObjectConstraint.NOT_NULL, ObjectConstraint.NULL);
List<HappyPathYield> nullConstraintOnResult = methodBehavior.happyPathYields().filter(my -> ObjectConstraint.NULL.equals(my.resultConstraint().get(ObjectConstraint.class))).collect(Collectors.toList());
assertThat(nullConstraintOnResult).hasSize(1);
HappyPathYield nullConstraintResult = nullConstraintOnResult.get(0);
Collection<ProgramState> ps = nullConstraintResult.statesAfterInvocation(invocationArguments, Lists.newArrayList(), ProgramState.EMPTY_STATE, () -> svResult).collect(Collectors.toList());
assertThat(ps).hasSize(1);
ObjectConstraint constraint = ps.iterator().next().getConstraint(svsecondArg, ObjectConstraint.class);
assertThat(constraint).isSameAs(ObjectConstraint.NULL);
}
use of org.sonar.java.se.constraint.ObjectConstraint in project sonar-java by SonarSource.
the class MethodBehaviorTest method method_behavior_yields.
@Test
public void method_behavior_yields() {
SymbolicExecutionVisitor sev = createSymbolicExecutionVisitor("src/test/resources/se/MethodYields.java");
MethodBehavior mb = getMethodBehavior(sev, "method");
List<MethodYield> yields = mb.yields();
assertThat(yields).hasSize(3);
List<HappyPathYield> trueResults = mb.happyPathYields().filter(my -> BooleanConstraint.TRUE.equals(my.resultConstraint().get(BooleanConstraint.class))).collect(Collectors.toList());
assertThat(trueResults).hasSize(1);
HappyPathYield trueResult = trueResults.get(0);
// 'a' has constraint "null"
assertThat(((ObjectConstraint) trueResult.parametersConstraints.get(0).get(ObjectConstraint.class)).isNull()).isTrue();
// no constraint on 'b'
assertThat(((ObjectConstraint) trueResult.parametersConstraints.get(0).get(ObjectConstraint.class)).isNull()).isTrue();
// result SV is a different SV than 'a' and 'b'
assertThat(trueResult.resultIndex()).isEqualTo(-1);
List<HappyPathYield> falseResults = mb.happyPathYields().filter(my -> BooleanConstraint.FALSE.equals(my.resultConstraint().get(BooleanConstraint.class))).collect(Collectors.toList());
assertThat(falseResults).hasSize(2);
// for both "False" results, 'a' has the constraint "not null"
assertThat(falseResults.stream().filter(my -> !((ObjectConstraint) my.parametersConstraints.get(0).get(ObjectConstraint.class)).isNull()).count()).isEqualTo(2);
// 1) 'b' has constraint "false", result is 'b'
assertThat(falseResults.stream().filter(my -> BooleanConstraint.FALSE.equals(my.parametersConstraints.get(1).get(BooleanConstraint.class)) && my.resultIndex() == 1).count()).isEqualTo(1);
// 2) 'b' is "true", result is a different SV than 'a' and 'b'
assertThat(falseResults.stream().filter(my -> BooleanConstraint.TRUE.equals(my.parametersConstraints.get(1).get(BooleanConstraint.class)) && my.resultIndex() == -1).count()).isEqualTo(1);
}
Aggregations