Search in sources :

Example 1 with ConstraintManager

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

the class ExplodedGraphWalker method execute.

private void execute(MethodTree tree) {
    CFG cfg = CFG.build(tree);
    exitBlock = cfg.exitBlock();
    checkerDispatcher.init(tree, cfg);
    liveVariables = LiveVariables.analyze(cfg);
    explodedGraph = new ExplodedGraph();
    methodTree = tree;
    constraintManager = new ConstraintManager();
    workList = new LinkedList<>();
    // Linked hashSet is required to guarantee order of yields to be generated
    endOfExecutionPath = new LinkedHashSet<>();
    if (DEBUG_MODE_ACTIVATED) {
        LOG.debug("Exploring Exploded Graph for method " + tree.simpleName().name() + " at line " + ((JavaTree) tree).getLine());
    }
    programState = ProgramState.EMPTY_STATE;
    steps = 0;
    for (ProgramState startingState : startingStates(tree, programState)) {
        enqueue(new ProgramPoint(cfg.entry()), startingState);
    }
    while (!workList.isEmpty()) {
        steps++;
        if (steps > maxSteps()) {
            throwMaxSteps(tree);
        }
        // LIFO:
        setNode(workList.removeFirst());
        CFG.Block block = (CFG.Block) programPosition.block;
        if (block.successors().isEmpty()) {
            endOfExecutionPath.add(node);
            continue;
        }
        try {
            Tree terminator = block.terminator();
            if (programPosition.i < block.elements().size()) {
                // process block element
                visit(block.elements().get(programPosition.i), terminator);
            } else if (terminator == null) {
                // process block exit, which is unconditional jump such as goto-statement or return-statement
                handleBlockExit(programPosition);
            } else if (programPosition.i == block.elements().size()) {
                // process block exist, which is conditional jump such as if-statement
                checkerDispatcher.executeCheckPostStatement(terminator);
            } else {
                // process branch
                // process block exist, which is conditional jump such as if-statement
                checkerDispatcher.executeCheckPreStatement(terminator);
                handleBlockExit(programPosition);
            }
        } catch (TooManyNestedBooleanStatesException e) {
            throwTooManyBooleanStates(tree, e);
        } catch (RelationalSymbolicValue.TransitiveRelationExceededException e) {
            throwTooManyTransitiveRelationsException(tree, e);
        }
    }
    handleEndOfExecutionPath(false);
    checkerDispatcher.executeCheckEndOfExecution();
    // Cleanup:
    workList = null;
    node = null;
    programState = null;
    constraintManager = null;
}
Also used : ConstraintManager(org.sonar.java.se.constraint.ConstraintManager) CFG(org.sonar.java.cfg.CFG) RelationalSymbolicValue(org.sonar.java.se.symbolicvalues.RelationalSymbolicValue) JavaTree(org.sonar.java.model.JavaTree) BlockTree(org.sonar.plugins.java.api.tree.BlockTree) IfStatementTree(org.sonar.plugins.java.api.tree.IfStatementTree) MemberSelectExpressionTree(org.sonar.plugins.java.api.tree.MemberSelectExpressionTree) NewArrayTree(org.sonar.plugins.java.api.tree.NewArrayTree) JavaTree(org.sonar.java.model.JavaTree) TypeCastTree(org.sonar.plugins.java.api.tree.TypeCastTree) NewClassTree(org.sonar.plugins.java.api.tree.NewClassTree) AssignmentExpressionTree(org.sonar.plugins.java.api.tree.AssignmentExpressionTree) IdentifierTree(org.sonar.plugins.java.api.tree.IdentifierTree) ThrowStatementTree(org.sonar.plugins.java.api.tree.ThrowStatementTree) ExpressionTree(org.sonar.plugins.java.api.tree.ExpressionTree) ForStatementTree(org.sonar.plugins.java.api.tree.ForStatementTree) VariableTree(org.sonar.plugins.java.api.tree.VariableTree) ArrayDimensionTree(org.sonar.plugins.java.api.tree.ArrayDimensionTree) BinaryExpressionTree(org.sonar.plugins.java.api.tree.BinaryExpressionTree) ReturnStatementTree(org.sonar.plugins.java.api.tree.ReturnStatementTree) LiteralTree(org.sonar.plugins.java.api.tree.LiteralTree) ConditionalExpressionTree(org.sonar.plugins.java.api.tree.ConditionalExpressionTree) Tree(org.sonar.plugins.java.api.tree.Tree) ArrayAccessExpressionTree(org.sonar.plugins.java.api.tree.ArrayAccessExpressionTree) WhileStatementTree(org.sonar.plugins.java.api.tree.WhileStatementTree) MethodInvocationTree(org.sonar.plugins.java.api.tree.MethodInvocationTree) DoWhileStatementTree(org.sonar.plugins.java.api.tree.DoWhileStatementTree) MethodTree(org.sonar.plugins.java.api.tree.MethodTree)

Example 2 with ConstraintManager

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

the class SymbolicValueFactoryTest method testFactory.

@Test
public void testFactory() {
    final IdentifierTree tree = new IdentifierTreeImpl(new InternalSyntaxToken(1, 1, "id", Collections.<SyntaxTrivia>emptyList(), 0, 0, false));
    final ConstraintManager manager = new ConstraintManager();
    SymbolicValue symbolicValue = manager.createSymbolicValue(tree);
    assertThat(symbolicValue.getClass()).as("Created without factory").isSameAs(SymbolicValue.class);
    manager.setValueFactory(new TestSymbolicValueFactory());
    symbolicValue = manager.createSymbolicValue(tree);
    assertThat(symbolicValue.getClass()).as("Created with factory").isSameAs(TestSymbolicValue.class);
    assertThat(symbolicValue.references(symbolicValue)).isFalse();
    manager.setValueFactory(new TestSymbolicValueFactory());
    try {
        manager.setValueFactory(new TestSymbolicValueFactory());
        fail("Able to add a second factory to the contraints manager");
    } catch (IllegalStateException e) {
        assertThat(e.getMessage()).as("Exception message").isEqualTo("The symbolic value factory has already been defined by another checker!");
    }
    symbolicValue = manager.createSymbolicValue(tree);
    assertThat(symbolicValue.getClass()).as("Created with first factory").isSameAs(TestSymbolicValue.class);
    symbolicValue = manager.createSymbolicValue(tree);
    assertThat(symbolicValue.getClass()).as("Created after factory usage").isSameAs(SymbolicValue.class);
}
Also used : ConstraintManager(org.sonar.java.se.constraint.ConstraintManager) IdentifierTreeImpl(org.sonar.java.model.expression.IdentifierTreeImpl) SyntaxTrivia(org.sonar.plugins.java.api.tree.SyntaxTrivia) IdentifierTree(org.sonar.plugins.java.api.tree.IdentifierTree) InternalSyntaxToken(org.sonar.java.model.InternalSyntaxToken) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue) Test(org.junit.Test)

Example 3 with ConstraintManager

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

the class ExplodedGraphWalker method executeMethodInvocation.

private void executeMethodInvocation(MethodInvocationTree mit) {
    setSymbolicValueOnFields(mit);
    // unstack arguments and method identifier
    ProgramState.Pop unstack = programState.unstackValue(mit.arguments().size() + 1);
    logState(mit);
    programState = unstack.state;
    // get method behavior for method with known declaration (ie: within the same file)
    MethodBehavior methodInvokedBehavior = null;
    Symbol methodSymbol = mit.symbol();
    if (methodSymbol.isMethodSymbol()) {
        methodInvokedBehavior = behaviorCache.get((Symbol.MethodSymbol) methodSymbol);
    }
    // Enqueue additional exceptional paths corresponding to unchecked exceptions, for instance OutOfMemoryError
    enqueueUncheckedExceptionalPaths(methodSymbol);
    final SymbolicValue resultValue = constraintManager.createMethodSymbolicValue(mit, unstack.valuesAndSymbols);
    if (methodInvokedBehavior != null && methodInvokedBehavior.isComplete() && !EQUALS_METHODS.anyMatch(mit)) {
        List<SymbolicValue> invocationArguments = invocationArguments(unstack.values);
        List<Type> invocationTypes = mit.arguments().stream().map(ExpressionTree::symbolType).collect(Collectors.toList());
        Map<Type, SymbolicValue.ExceptionalSymbolicValue> thrownExceptionsByExceptionType = new HashMap<>();
        // Enqueue exceptional paths from exceptional yields
        methodInvokedBehavior.exceptionalPathYields().forEach(yield -> yield.statesAfterInvocation(invocationArguments, invocationTypes, programState, () -> thrownExceptionsByExceptionType.computeIfAbsent(yield.exceptionType(semanticModel), constraintManager::createExceptionalSymbolicValue)).forEach(psYield -> enqueueExceptionalPaths(psYield, methodSymbol, yield)));
        // Enqueue happy paths
        methodInvokedBehavior.happyPathYields().forEach(yield -> yield.statesAfterInvocation(invocationArguments, invocationTypes, programState, () -> resultValue).map(psYield -> handleSpecialMethods(psYield, mit)).forEach(psYield -> enqueueHappyPath(psYield, mit, yield)));
    } else {
        // Enqueue exceptional paths from thrown exceptions
        enqueueThrownExceptionalPaths(methodSymbol);
        // Enqueue happy paths
        programState = handleSpecialMethods(programState.stackValue(resultValue), mit);
        checkerDispatcher.executeCheckPostStatement(mit);
        clearStack(mit);
    }
}
Also used : JavaSymbol(org.sonar.java.resolve.JavaSymbol) JavaFileScanner(org.sonar.plugins.java.api.JavaFileScanner) BlockTree(org.sonar.plugins.java.api.tree.BlockTree) ExpressionUtils(org.sonar.java.model.ExpressionUtils) MethodYield(org.sonar.java.se.xproc.MethodYield) Loggers(org.sonar.api.utils.log.Loggers) IfStatementTree(org.sonar.plugins.java.api.tree.IfStatementTree) NullDereferenceCheck(org.sonar.java.se.checks.NullDereferenceCheck) SECheck(org.sonar.java.se.checks.SECheck) RedundantAssignmentsCheck(org.sonar.java.se.checks.RedundantAssignmentsCheck) MemberSelectExpressionTree(org.sonar.plugins.java.api.tree.MemberSelectExpressionTree) Map(java.util.Map) MethodMatcher(org.sonar.java.matcher.MethodMatcher) BooleanConstraint(org.sonar.java.se.constraint.BooleanConstraint) ImmutableSet(com.google.common.collect.ImmutableSet) NewArrayTree(org.sonar.plugins.java.api.tree.NewArrayTree) Collection(java.util.Collection) Set(java.util.Set) JavaTree(org.sonar.java.model.JavaTree) TypeCastTree(org.sonar.plugins.java.api.tree.TypeCastTree) Collectors(java.util.stream.Collectors) NewClassTree(org.sonar.plugins.java.api.tree.NewClassTree) Objects(java.util.Objects) List(java.util.List) Stream(java.util.stream.Stream) DebugCheck(org.sonar.java.DebugCheck) StreamConsumedCheck(org.sonar.java.se.checks.StreamConsumedCheck) AssignmentExpressionTree(org.sonar.plugins.java.api.tree.AssignmentExpressionTree) NullableAnnotationUtils.isGloballyAnnotatedParameterNonNull(org.sonar.java.se.NullableAnnotationUtils.isGloballyAnnotatedParameterNonNull) IdentifierTree(org.sonar.plugins.java.api.tree.IdentifierTree) Symbol(org.sonar.plugins.java.api.semantic.Symbol) Joiner(com.google.common.base.Joiner) ObjectConstraint(org.sonar.java.se.constraint.ObjectConstraint) NullableAnnotationUtils.isAnnotatedNonNull(org.sonar.java.se.NullableAnnotationUtils.isAnnotatedNonNull) HashMap(java.util.HashMap) Deque(java.util.Deque) ThrowStatementTree(org.sonar.plugins.java.api.tree.ThrowStatementTree) NullableAnnotationUtils.isGloballyAnnotatedParameterNullable(org.sonar.java.se.NullableAnnotationUtils.isGloballyAnnotatedParameterNullable) ArrayList(java.util.ArrayList) ExpressionTree(org.sonar.plugins.java.api.tree.ExpressionTree) ForStatementTree(org.sonar.plugins.java.api.tree.ForStatementTree) VariableTree(org.sonar.plugins.java.api.tree.VariableTree) JavaType(org.sonar.java.resolve.JavaType) DivisionByZeroCheck(org.sonar.java.se.checks.DivisionByZeroCheck) ConstraintManager(org.sonar.java.se.constraint.ConstraintManager) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) NoWayOutLoopCheck(org.sonar.java.se.checks.NoWayOutLoopCheck) LiveVariables(org.sonar.java.cfg.LiveVariables) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue) MethodBehavior(org.sonar.java.se.xproc.MethodBehavior) ArrayDimensionTree(org.sonar.plugins.java.api.tree.ArrayDimensionTree) LinkedList(java.util.LinkedList) MethodMatcherCollection(org.sonar.java.matcher.MethodMatcherCollection) LinkedHashSet(java.util.LinkedHashSet) Nullable(javax.annotation.Nullable) Logger(org.sonar.api.utils.log.Logger) UnclosedResourcesCheck(org.sonar.java.se.checks.UnclosedResourcesCheck) BinaryExpressionTree(org.sonar.plugins.java.api.tree.BinaryExpressionTree) ReturnStatementTree(org.sonar.plugins.java.api.tree.ReturnStatementTree) LiteralTree(org.sonar.plugins.java.api.tree.LiteralTree) Types(org.sonar.java.resolve.Types) Iterator(java.util.Iterator) ConditionalExpressionTree(org.sonar.plugins.java.api.tree.ConditionalExpressionTree) Tree(org.sonar.plugins.java.api.tree.Tree) Type(org.sonar.plugins.java.api.semantic.Type) ArrayAccessExpressionTree(org.sonar.plugins.java.api.tree.ArrayAccessExpressionTree) RelationalSymbolicValue(org.sonar.java.se.symbolicvalues.RelationalSymbolicValue) WhileStatementTree(org.sonar.plugins.java.api.tree.WhileStatementTree) OptionalGetBeforeIsPresentCheck(org.sonar.java.se.checks.OptionalGetBeforeIsPresentCheck) MethodInvocationTree(org.sonar.plugins.java.api.tree.MethodInvocationTree) DoWhileStatementTree(org.sonar.plugins.java.api.tree.DoWhileStatementTree) NonNullSetToNullCheck(org.sonar.java.se.checks.NonNullSetToNullCheck) CFG(org.sonar.java.cfg.CFG) SemanticModel(org.sonar.java.resolve.SemanticModel) BehaviorCache(org.sonar.java.se.xproc.BehaviorCache) Preconditions(com.google.common.base.Preconditions) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) CheckForNull(javax.annotation.CheckForNull) LocksNotUnlockedCheck(org.sonar.java.se.checks.LocksNotUnlockedCheck) NullableAnnotationUtils.isAnnotatedNullable(org.sonar.java.se.NullableAnnotationUtils.isAnnotatedNullable) MethodTree(org.sonar.plugins.java.api.tree.MethodTree) HashMap(java.util.HashMap) JavaSymbol(org.sonar.java.resolve.JavaSymbol) Symbol(org.sonar.plugins.java.api.semantic.Symbol) JavaType(org.sonar.java.resolve.JavaType) Type(org.sonar.plugins.java.api.semantic.Type) MethodBehavior(org.sonar.java.se.xproc.MethodBehavior) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue) RelationalSymbolicValue(org.sonar.java.se.symbolicvalues.RelationalSymbolicValue)

Example 4 with ConstraintManager

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

the class NonNullSetToNullCheck method checkEndOfExecutionPath.

@Override
public void checkEndOfExecutionPath(CheckerContext context, ConstraintManager constraintManager) {
    if (methodTree.is(Tree.Kind.CONSTRUCTOR) && !isDefaultConstructorForJpa(methodTree) && !callsThisConstructor(methodTree) && !exitingWithException(context)) {
        ClassTree classTree = (ClassTree) methodTree.parent();
        classTree.members().stream().filter(m -> m.is(Tree.Kind.VARIABLE)).map(m -> (VariableTree) m).filter(v -> v.initializer() == null).forEach(v -> checkVariable(context, methodTree, v.symbol()));
    }
}
Also used : ObjectConstraint(org.sonar.java.se.constraint.ObjectConstraint) JavaSymbol(org.sonar.java.resolve.JavaSymbol) ProgramState(org.sonar.java.se.ProgramState) ExpressionUtils(org.sonar.java.model.ExpressionUtils) NullableAnnotationUtils.nonNullAnnotation(org.sonar.java.se.NullableAnnotationUtils.nonNullAnnotation) MessageFormat(java.text.MessageFormat) CheckerContext(org.sonar.java.se.CheckerContext) ExpressionTree(org.sonar.plugins.java.api.tree.ExpressionTree) VariableTree(org.sonar.plugins.java.api.tree.VariableTree) ConstraintManager(org.sonar.java.se.constraint.ConstraintManager) Lists(com.google.common.collect.Lists) SymbolMetadata(org.sonar.plugins.java.api.semantic.SymbolMetadata) MemberSelectExpressionTree(org.sonar.plugins.java.api.tree.MemberSelectExpressionTree) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue) Nullable(javax.annotation.Nullable) Arguments(org.sonar.plugins.java.api.tree.Arguments) ReturnStatementTree(org.sonar.plugins.java.api.tree.ReturnStatementTree) ExpressionStatementTree(org.sonar.plugins.java.api.tree.ExpressionStatementTree) StatementTree(org.sonar.plugins.java.api.tree.StatementTree) Tree(org.sonar.plugins.java.api.tree.Tree) MethodInvocationTree(org.sonar.plugins.java.api.tree.MethodInvocationTree) NewClassTree(org.sonar.plugins.java.api.tree.NewClassTree) List(java.util.List) Stream(java.util.stream.Stream) CFG(org.sonar.java.cfg.CFG) AssignmentExpressionTree(org.sonar.plugins.java.api.tree.AssignmentExpressionTree) ClassTree(org.sonar.plugins.java.api.tree.ClassTree) Rule(org.sonar.check.Rule) IdentifierTree(org.sonar.plugins.java.api.tree.IdentifierTree) Symbol(org.sonar.plugins.java.api.semantic.Symbol) MethodTree(org.sonar.plugins.java.api.tree.MethodTree) NewClassTree(org.sonar.plugins.java.api.tree.NewClassTree) ClassTree(org.sonar.plugins.java.api.tree.ClassTree)

Aggregations

ConstraintManager (org.sonar.java.se.constraint.ConstraintManager)4 IdentifierTree (org.sonar.plugins.java.api.tree.IdentifierTree)4 CFG (org.sonar.java.cfg.CFG)3 SymbolicValue (org.sonar.java.se.symbolicvalues.SymbolicValue)3 AssignmentExpressionTree (org.sonar.plugins.java.api.tree.AssignmentExpressionTree)3 ExpressionTree (org.sonar.plugins.java.api.tree.ExpressionTree)3 MemberSelectExpressionTree (org.sonar.plugins.java.api.tree.MemberSelectExpressionTree)3 MethodInvocationTree (org.sonar.plugins.java.api.tree.MethodInvocationTree)3 MethodTree (org.sonar.plugins.java.api.tree.MethodTree)3 NewClassTree (org.sonar.plugins.java.api.tree.NewClassTree)3 ReturnStatementTree (org.sonar.plugins.java.api.tree.ReturnStatementTree)3 Tree (org.sonar.plugins.java.api.tree.Tree)3 VariableTree (org.sonar.plugins.java.api.tree.VariableTree)3 Lists (com.google.common.collect.Lists)2 List (java.util.List)2 Stream (java.util.stream.Stream)2 Nullable (javax.annotation.Nullable)2 ExpressionUtils (org.sonar.java.model.ExpressionUtils)2 JavaSymbol (org.sonar.java.resolve.JavaSymbol)2 ObjectConstraint (org.sonar.java.se.constraint.ObjectConstraint)2