Search in sources :

Example 1 with ProgramState

use of org.sonar.java.se.ProgramState in project sonar-java by SonarSource.

the class MethodYieldTest method constraints_on_varargs.

@Test
public void constraints_on_varargs() throws Exception {
    ActionParser<Tree> p = JavaParser.createParser();
    CompilationUnitTree cut = (CompilationUnitTree) p.parse(new File("src/test/files/se/VarArgsYields.java"));
    SemanticModel semanticModel = SemanticModel.createFor(cut, new SquidClassLoader(new ArrayList<>()));
    SymbolicExecutionVisitor sev = new SymbolicExecutionVisitor(Lists.newArrayList(new SECheck[] {}), new BehaviorCache(new SquidClassLoader(new ArrayList<>())));
    JavaFileScannerContext context = mock(JavaFileScannerContext.class);
    when(context.getTree()).thenReturn(cut);
    when(context.getSemanticModel()).thenReturn(semanticModel);
    sev.scanFile(context);
    MethodSymbol methodSymbol = ((MethodTree) ((ClassTree) cut.types().get(0)).members().get(0)).symbol();
    MethodBehavior mb = getMethodBehavior(sev, "varArgMethod");
    List<MethodYield> yields = mb.yields();
    assertThat(yields).hasSize(5);
    assertThat(mb.exceptionalPathYields()).hasSize(4);
    MethodYield yield = mb.happyPathYields().findFirst().get();
    // check that we have NOT_NULL constraint on the first argument
    assertThat(yield.parametersConstraints.get(0).get(ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    // check that we have NOT_NULL constraint on the variadic argument
    assertThat(yield.parametersConstraints.get(1).get(ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    List<IdentifierTree> usages = methodSymbol.usages();
    assertThat(usages).hasSize(6);
    List<List<Type>> arguments = usages.stream().map(MethodYieldTest::getMethodIncoationArgumentsTypes).collect(Collectors.toList());
    ProgramState ps = ProgramState.EMPTY_STATE;
    ProgramState psResult;
    SymbolicValue svFirstArg = new SymbolicValue();
    SymbolicValue svVarArg1 = new SymbolicValue();
    SymbolicValue svVarArg2 = new SymbolicValue();
    SymbolicValue svResult = new SymbolicValue();
    // apply constraint NotNull to parameter
    Collection<ProgramState> arrayOfA = yield.statesAfterInvocation(Lists.newArrayList(svFirstArg, svVarArg1), arguments.get(0), ps, () -> svResult).collect(Collectors.toList());
    assertThat(arrayOfA).hasSize(1);
    psResult = arrayOfA.iterator().next();
    assertThat(psResult.getConstraint(svFirstArg, ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    assertThat(psResult.getConstraint(svVarArg1, ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    // apply constraint NotNull to parameter (B[] is a subtype of A[])
    Collection<ProgramState> arrayOfB = yield.statesAfterInvocation(Lists.newArrayList(svFirstArg, svVarArg1), arguments.get(1), ps, () -> svResult).collect(Collectors.toList());
    assertThat(arrayOfB).hasSize(1);
    psResult = arrayOfB.iterator().next();
    assertThat(psResult.getConstraint(svFirstArg, ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    assertThat(psResult.getConstraint(svVarArg1, ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    // no constraint, as 'a' is not an array
    Collection<ProgramState> objectA = yield.statesAfterInvocation(Lists.newArrayList(svFirstArg, svVarArg1), arguments.get(2), ps, () -> svResult).collect(Collectors.toList());
    assertThat(objectA).hasSize(1);
    psResult = objectA.iterator().next();
    assertThat(psResult.getConstraint(svFirstArg, ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    assertThat(psResult.getConstraint(svVarArg1, ObjectConstraint.class)).isNull();
    // no constraint, as 'a' and 'b' can not receive the constraint of the array
    Collection<ProgramState> objectsAandB = yield.statesAfterInvocation(Lists.newArrayList(svFirstArg, svVarArg1, svVarArg2), arguments.get(3), ps, () -> svResult).collect(Collectors.toList());
    assertThat(objectsAandB).hasSize(1);
    psResult = objectsAandB.iterator().next();
    assertThat(psResult.getConstraint(svFirstArg, ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    assertThat(psResult.getConstraint(svVarArg1, ObjectConstraint.class)).isNull();
    assertThat(psResult.getConstraint(svVarArg2, ObjectConstraint.class)).isNull();
    // no param, we only learn something about the argument which is not variadic
    Collection<ProgramState> noParam = yield.statesAfterInvocation(Lists.newArrayList(svFirstArg), arguments.get(4), ps, () -> svResult).collect(Collectors.toList());
    assertThat(noParam).hasSize(1);
    psResult = noParam.iterator().next();
    assertThat(psResult.getConstraint(svFirstArg, ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    // null param, contradiction, no resulting program state
    ps = ProgramState.EMPTY_STATE.addConstraint(svFirstArg, ObjectConstraint.NULL);
    Collection<ProgramState> nullParam = yield.statesAfterInvocation(Lists.newArrayList(svFirstArg, svVarArg1), arguments.get(5), ps, () -> svResult).collect(Collectors.toList());
    assertThat(nullParam).isEmpty();
}
Also used : MethodTree(org.sonar.plugins.java.api.tree.MethodTree) ArrayList(java.util.ArrayList) ClassTree(org.sonar.plugins.java.api.tree.ClassTree) IdentifierTree(org.sonar.plugins.java.api.tree.IdentifierTree) ProgramState(org.sonar.java.se.ProgramState) SquidClassLoader(org.sonar.java.bytecode.loader.SquidClassLoader) SECheck(org.sonar.java.se.checks.SECheck) JavaFileScannerContext(org.sonar.plugins.java.api.JavaFileScannerContext) CompilationUnitTree(org.sonar.plugins.java.api.tree.CompilationUnitTree) ClassTree(org.sonar.plugins.java.api.tree.ClassTree) IdentifierTree(org.sonar.plugins.java.api.tree.IdentifierTree) ExpressionTree(org.sonar.plugins.java.api.tree.ExpressionTree) Tree(org.sonar.plugins.java.api.tree.Tree) MethodInvocationTree(org.sonar.plugins.java.api.tree.MethodInvocationTree) MethodTree(org.sonar.plugins.java.api.tree.MethodTree) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue) CompilationUnitTree(org.sonar.plugins.java.api.tree.CompilationUnitTree) SemanticModel(org.sonar.java.resolve.SemanticModel) SETestUtils.createSymbolicExecutionVisitor(org.sonar.java.se.SETestUtils.createSymbolicExecutionVisitor) SymbolicExecutionVisitor(org.sonar.java.se.SymbolicExecutionVisitor) MethodSymbol(org.sonar.plugins.java.api.semantic.Symbol.MethodSymbol) SETestUtils.mockMethodBehavior(org.sonar.java.se.SETestUtils.mockMethodBehavior) SETestUtils.getMethodBehavior(org.sonar.java.se.SETestUtils.getMethodBehavior) File(java.io.File) Test(org.junit.Test)

Example 2 with ProgramState

use of org.sonar.java.se.ProgramState 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);
}
Also used : MethodInvocationTree(org.sonar.plugins.java.api.tree.MethodInvocationTree) ObjectConstraint(org.sonar.java.se.constraint.ObjectConstraint) ProgramState(org.sonar.java.se.ProgramState) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue)

Example 3 with ProgramState

use of org.sonar.java.se.ProgramState 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);
}
Also used : MethodInvocationTree(org.sonar.plugins.java.api.tree.MethodInvocationTree) ObjectConstraint(org.sonar.java.se.constraint.ObjectConstraint) ProgramState(org.sonar.java.se.ProgramState) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue)

Example 4 with ProgramState

use of org.sonar.java.se.ProgramState in project sonar-java by SonarSource.

the class RedundantAssignmentsCheck method handleAssignment.

private void handleAssignment(CheckerContext context, AssignmentExpressionTree assignmentExpressionTree) {
    SymbolicValueSymbol assignedVariable = context.getState().peekValueSymbol();
    Symbol assignedSymbol = assignedVariable.symbol();
    if (assignedSymbol == null || // meaning that 'stream = stream.map(...);' would be detected as redundant assignment if not explicitly excluded
    STREAM_TYPES.stream().anyMatch(assignedSymbol.type()::is)) {
        return;
    }
    ExplodedGraph.Node node = context.getNode();
    ProgramState previousState = node.programState;
    SymbolicValue oldValue = previousState.getValue(assignedSymbol);
    SymbolicValue newValue = assignedVariable.symbolicValue();
    Symbol fromSymbol = previousState.peekValueSymbol().symbol();
    assignmentsByMethod.peek().put(assignmentExpressionTree, new AssignmentDataHolder(assignedSymbol, oldValue, newValue, fromSymbol, node));
}
Also used : ExplodedGraph(org.sonar.java.se.ExplodedGraph) SymbolicValueSymbol(org.sonar.java.se.ProgramState.SymbolicValueSymbol) SymbolicValueSymbol(org.sonar.java.se.ProgramState.SymbolicValueSymbol) Symbol(org.sonar.plugins.java.api.semantic.Symbol) ProgramState(org.sonar.java.se.ProgramState) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue)

Example 5 with ProgramState

use of org.sonar.java.se.ProgramState 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;
}
Also used : ObjectConstraint(org.sonar.java.se.constraint.ObjectConstraint) ProgramState(org.sonar.java.se.ProgramState)

Aggregations

ProgramState (org.sonar.java.se.ProgramState)105 SymbolicValue (org.sonar.java.se.symbolicvalues.SymbolicValue)72 Test (org.junit.Test)71 Instruction (org.sonar.java.bytecode.cfg.Instruction)61 RelationalSymbolicValue (org.sonar.java.se.symbolicvalues.RelationalSymbolicValue)52 BinarySymbolicValue (org.sonar.java.se.symbolicvalues.BinarySymbolicValue)45 BooleanConstraint (org.sonar.java.se.constraint.BooleanConstraint)33 ObjectConstraint (org.sonar.java.se.constraint.ObjectConstraint)32 ProgramPoint (org.sonar.java.se.ProgramPoint)30 Constraint (org.sonar.java.se.constraint.Constraint)30 TypedConstraint (org.sonar.java.se.constraint.TypedConstraint)25 ConstraintsByDomain (org.sonar.java.se.constraint.ConstraintsByDomain)11 List (java.util.List)9 Collectors (java.util.stream.Collectors)8 Type (org.sonar.plugins.java.api.semantic.Type)8 VisibleForTesting (com.google.common.annotations.VisibleForTesting)7 ExplodedGraph (org.sonar.java.se.ExplodedGraph)7 MethodInvocationTree (org.sonar.plugins.java.api.tree.MethodInvocationTree)7 Lists (com.google.common.collect.Lists)6 ArrayList (java.util.ArrayList)6