public ExplodedGraphWalker createWalker(BehaviorCache behaviorCache, SemanticModel semanticModel) { return new ExplodedGraphWalker(seChecks, behaviorCache, semanticModel); }
private void enqueueHappyPath(ProgramState programState, MethodInvocationTree mit, MethodYield yield) { checkerDispatcher.syntaxNode = mit; checkerDispatcher.methodYield = yield; checkerDispatcher.addTransition(programState); checkerDispatcher.methodYield = null; clearStack(mit); }
public void enqueue(ProgramPoint programPoint, ProgramState programState) { enqueue(programPoint, programState, false); }
executeMethodInvocation(mit); return; case LABELED_STATEMENT: throw new IllegalStateException("Cannot appear in CFG: " + tree.kind().name()); case VARIABLE: executeVariable((VariableTree) tree, terminator); break; case TYPE_CAST: executeTypeCast((TypeCastTree) tree); break; case ASSIGNMENT: case RIGHT_SHIFT_ASSIGNMENT: case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: executeAssignment((AssignmentExpressionTree) tree); break; case AND_ASSIGNMENT: case XOR_ASSIGNMENT: case OR_ASSIGNMENT: executeLogicalAssignment((AssignmentExpressionTree) tree); break; case ARRAY_ACCESS_EXPRESSION: executeArrayAccessExpression((ArrayAccessExpressionTree) tree); break; case NEW_ARRAY: executeNewArray((NewArrayTree) tree); break; case NEW_CLASS:
executeMethodInvocation((MethodInvocationTree) tree); break; case LABELED_STATEMENT: throw new IllegalStateException("Cannot appear in CFG: " + tree.kind().name()); case VARIABLE: executeVariable((VariableTree) tree, terminator); break; case TYPE_CAST: executeTypeCast((TypeCastTree) tree); break; case ASSIGNMENT: case RIGHT_SHIFT_ASSIGNMENT: case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: executeAssignement((AssignmentExpressionTree) tree); break; case AND_ASSIGNMENT: case XOR_ASSIGNMENT: case OR_ASSIGNMENT: executeLogicalAssignement((AssignmentExpressionTree) tree); break; case ARRAY_ACCESS_EXPRESSION: executeArrayAccessExpression((ArrayAccessExpressionTree) tree); break; case NEW_ARRAY: executeNewArray((NewArrayTree) tree); break; case NEW_CLASS:
for (ProgramState startingState : startingStates(tree, programState)) { enqueue(new ProgramPoint(cfg.entryBlock()), startingState); if (steps > maxSteps()) { throwMaxSteps(tree); setNode(workList.removeFirst()); CFG.Block block = (CFG.Block) programPosition.block; if (block.successors().isEmpty()) { if (programPosition.i < block.elements().size()) { visit(block.elements().get(programPosition.i), terminator); } else if (terminator == null) { handleBlockExit(programPosition); } else if (programPosition.i == block.elements().size()) { handleBlockExit(programPosition); throwTooManyBooleanStates(tree, e); } catch (RelationalSymbolicValue.TransitiveRelationExceededException e) { throwTooManyTransitiveRelationsException(tree, e); handleEndOfExecutionPath(false); checkerDispatcher.executeCheckEndOfExecution();
private void executeMethodInvocation(MethodInvocationTree mit) { setSymbolicValueOnFields(mit); logState(mit); enqueueUncheckedExceptionalPaths(methodSymbol); && methodInvokedBehavior.isComplete() && !EQUALS_METHODS.anyMatch(mit)) { List<SymbolicValue> invocationArguments = invocationArguments(unstack.values); List<Type> invocationTypes = mit.arguments().stream().map(ExpressionTree::symbolType).collect(Collectors.toList()); programState, () -> thrownExceptionsByExceptionType.computeIfAbsent(yield.exceptionType(semanticModel), constraintManager::createExceptionalSymbolicValue)) .forEach(psYield -> enqueueExceptionalPaths(psYield, methodSymbol, yield))); .forEach(yield -> yield.statesAfterInvocation(invocationArguments, invocationTypes, programState, () -> resultValue) .map(psYield -> handleSpecialMethods(psYield, mit)) .forEach(psYield -> enqueueHappyPath(psYield, mit, yield))); } else { enqueueThrownExceptionalPaths(methodSymbol); programState = handleSpecialMethods(programState.stackValue(resultValue), mit); checkerDispatcher.executeCheckPostStatement(mit); clearStack(mit);
private void handleBlockExit(ProgramPoint programPosition) { CFG.Block block = (CFG.Block) programPosition.block; Tree terminator = block.terminator(); cleanUpProgramState(block); boolean exitPath = node.exitPath; if (terminator != null) { case IF_STATEMENT: ExpressionTree ifCondition = ((IfStatementTree) terminator).condition(); handleBranch(block, cleanupCondition(ifCondition), verifyCondition(ifCondition)); return; case CONDITIONAL_OR: case CONDITIONAL_AND: handleBranch(block, ((BinaryExpressionTree) terminator).leftOperand()); return; case CONDITIONAL_EXPRESSION: handleBranch(block, ((ConditionalExpressionTree) terminator).condition()); return; case FOR_STATEMENT: ExpressionTree condition = ((ForStatementTree) terminator).condition(); if (condition != null) { handleBranch(block, condition, false); return; case WHILE_STATEMENT: ExpressionTree whileCondition = ((WhileStatementTree) terminator).condition(); handleBranch(block, cleanupCondition(whileCondition), verifyCondition(whileCondition)); return; case DO_STATEMENT: ExpressionTree doCondition = ((DoWhileStatementTree) terminator).condition();
private void handleBlockExit(ExplodedGraph.ProgramPoint programPosition) { CFG.Block block = programPosition.block; Tree terminator = block.terminator(); cleanUpProgramState(block); if (terminator != null) { switch (terminator.kind()) { case IF_STATEMENT: handleBranch(block, cleanupCondition(((IfStatementTree) terminator).condition())); return; case CONDITIONAL_OR: case CONDITIONAL_AND: handleBranch(block, ((BinaryExpressionTree) terminator).leftOperand()); return; case CONDITIONAL_EXPRESSION: handleBranch(block, ((ConditionalExpressionTree) terminator).condition()); return; case FOR_STATEMENT: ExpressionTree condition = ((ForStatementTree) terminator).condition(); if (condition != null) { handleBranch(block, condition, false); return; case WHILE_STATEMENT: ExpressionTree whileCondition = ((WhileStatementTree) terminator).condition(); handleBranch(block, cleanupCondition(whileCondition), !whileCondition.is(Tree.Kind.BOOLEAN_LITERAL)); return; case DO_STATEMENT: ExpressionTree doCondition = ((DoWhileStatementTree) terminator).condition(); handleBranch(block, cleanupCondition(doCondition), !doCondition.is(Tree.Kind.BOOLEAN_LITERAL)); return;
programState = ProgramState.EMPTY_STATE; steps = 0; for (ProgramState startingState : startingStates(tree, programState)) { enqueue(new ExplodedGraph.ProgramPoint(cfg.entry(), 0), startingState); if (programPosition.i < programPosition.block.elements().size()) { visit(programPosition.block.elements().get(programPosition.i), programPosition.block.terminator()); } else if (programPosition.block.terminator() == null) { handleBlockExit(programPosition); } else if (programPosition.i == programPosition.block.elements().size()) { handleBlockExit(programPosition);
public void enqueue(ProgramPoint newProgramPoint, ProgramState programState, boolean exitPath, @Nullable MethodYield methodYield) { ProgramPoint programPoint = newProgramPoint; int nbOfExecution = programState.numberOfTimeVisited(programPoint); if (nbOfExecution > MAX_EXEC_PROGRAM_POINT) { if (isRestartingForEachLoop(programPoint)) { // reached the max number of visit by program point, so take the false branch with current program state programPoint = new ProgramPoint(((CFG.Block) programPoint.block).falseBlock()); } else { debugPrint(programPoint); return; } } checkExplodedGraphTooBig(programState); ProgramState ps = programState.visitedPoint(programPoint, nbOfExecution + 1); ExplodedGraph.Node cachedNode = explodedGraph.node(programPoint, ps); if (!cachedNode.isNew() && exitPath == cachedNode.exitPath) { // has been enqueued earlier cachedNode.addParent(node, methodYield); return; } cachedNode.exitPath = exitPath; cachedNode.addParent(node, methodYield); workList.addFirst(cachedNode); }
for (ProgramState state : pair.a) { ProgramState ps = state; if (condition.parent().is(Tree.Kind.CONDITIONAL_AND) && !isPartOfConditionalExpressionCondition(condition)) { enqueue(falseBlockProgramPoint, ps, node.exitPath); if (checkPath) { alwaysTrueOrFalseExpressionCollector.evaluatedToFalse(cleanupCondition((ExpressionTree) condition), node); for (ProgramState state : pair.b) { ProgramState ps = state; if (condition.parent().is(Tree.Kind.CONDITIONAL_OR) && !isPartOfConditionalExpressionCondition(condition)) { enqueue(trueBlockProgramPoint, ps, node.exitPath); if (checkPath) { alwaysTrueOrFalseExpressionCollector.evaluatedToTrue(cleanupCondition((ExpressionTree) condition), node);
private void executePost() { this.transition = false; if (currentCheckerIndex < checks.size()) { explodedGraphWalker.programState = checks.get(currentCheckerIndex).checkPostStatement(this, syntaxNode); } else { CFG.Block block = (CFG.Block) explodedGraphWalker.programPosition.block; if (explodedGraphWalker.programPosition.i< block.elements().size()) { explodedGraphWalker.clearStack(block.elements().get(explodedGraphWalker.programPosition.i)); } explodedGraphWalker.enqueue( explodedGraphWalker.programPosition.next(), explodedGraphWalker.programState, explodedGraphWalker.node.exitPath, methodYield); return; } if (!transition) { addTransition(explodedGraphWalker.programState); } }
public void enqueue(ExplodedGraph.ProgramPoint programPoint, ProgramState programState, boolean exitPath) { int nbOfExecution = programState.numberOfTimeVisited(programPoint); if (nbOfExecution > MAX_EXEC_PROGRAM_POINT) { debugPrint(programState); return; } checkExplodedGraphTooBig(programState); ExplodedGraph.Node cachedNode = explodedGraph.getNode(programPoint, programState.visitedPoint(programPoint, nbOfExecution + 1)); if (!cachedNode.isNew && exitPath == cachedNode.exitPath) { // has been enqueued earlier return; } cachedNode.exitPath = exitPath; workList.addFirst(cachedNode); }
.filter(b -> isCaughtByBlock(exceptionSV.exceptionType(), b)) .sorted((b1, b2) -> Integer.compare(b2.id(), b1.id())) .collect(Collectors.toList()); if (!caughtBlocks.isEmpty()) { caughtBlocks.forEach(b -> enqueue(new ProgramPoint(b), ps, methodYield)); return; .forEach(b -> enqueue(new ProgramPoint(b), ps, methodYield)); .findFirst() .orElse(exitBlock); enqueue(new ProgramPoint(methodExit), ps, true, methodYield); } else { otherBlocks.forEach(b -> enqueue(new ProgramPoint(b), ps, true, methodYield));
public MethodBehavior visitMethod(MethodTree tree, @Nullable MethodBehavior methodBehavior) { Preconditions.checkArgument(methodBehavior == null || !methodBehavior.isComplete() || !methodBehavior.isVisited(), "Trying to execute an already visited methodBehavior"); this.methodBehavior = methodBehavior; BlockTree body = tree.block(); if (body != null) { execute(tree); } return this.methodBehavior; }
private void logState(MethodInvocationTree mit) { if (mit.methodSelect().is(Tree.Kind.IDENTIFIER) && "printState".equals(((IdentifierTree) mit.methodSelect()).name())) { debugPrint(((JavaTree) mit).getLine(), node); } }
/** * Required for accurate reporting. * If condition is && or || expression, then return its right operand. */ private static ExpressionTree cleanupCondition(ExpressionTree condition) { ExpressionTree cleanedUpCondition = ExpressionUtils.skipParentheses(condition); if (cleanedUpCondition.is(Tree.Kind.CONDITIONAL_AND, Tree.Kind.CONDITIONAL_OR)) { cleanedUpCondition = cleanupCondition(((BinaryExpressionTree) cleanedUpCondition).rightOperand()); } return cleanedUpCondition; }
executeMethodInvocation(mit); return; case LABELED_STATEMENT: throw new IllegalStateException("Cannot appear in CFG: " + tree.kind().name()); case VARIABLE: executeVariable((VariableTree) tree, terminator); break; case TYPE_CAST: executeTypeCast((TypeCastTree) tree); break; case ASSIGNMENT: case RIGHT_SHIFT_ASSIGNMENT: case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: executeAssignment((AssignmentExpressionTree) tree); break; case AND_ASSIGNMENT: case XOR_ASSIGNMENT: case OR_ASSIGNMENT: executeLogicalAssignment((AssignmentExpressionTree) tree); break; case ARRAY_ACCESS_EXPRESSION: executeArrayAccessExpression((ArrayAccessExpressionTree) tree); break; case NEW_ARRAY: executeNewArray((NewArrayTree) tree); break; case NEW_CLASS:
for (ProgramState startingState : startingStates(tree, programState)) { enqueue(new ProgramPoint(cfg.entryBlock()), startingState); if (steps > maxSteps()) { throwMaxSteps(tree); setNode(workList.removeFirst()); CFG.Block block = (CFG.Block) programPosition.block; if (block.successors().isEmpty()) { if (programPosition.i < block.elements().size()) { visit(block.elements().get(programPosition.i), terminator); } else if (terminator == null) { handleBlockExit(programPosition); } else if (programPosition.i == block.elements().size()) { handleBlockExit(programPosition); throwTooManyBooleanStates(tree, e); } catch (RelationalSymbolicValue.TransitiveRelationExceededException e) { throwTooManyTransitiveRelationsException(tree, e); handleEndOfExecutionPath(false); checkerDispatcher.executeCheckEndOfExecution();