Example #1
0
        internal Explorer(
            ExplorationContext explorationContext,
            IContextFactory smtContextFactory,
            StartingNodeInfo startingNode,
            IEntryPointRecognizer finalNodeRecognizer,
            ISymbolicHeapFactory heapFactory,
            Action <ExplorationResult> resultCallback)
        {
            // TODO: Solve this marginal case directly in the ExplorationContext
            Contract.Requires(!finalNodeRecognizer.IsFinalNode(startingNode.Node));

            this.context             = explorationContext;
            this.startingNode        = startingNode;
            this.finalNodeRecognizer = finalNodeRecognizer;
            this.heapFactory         = heapFactory;
            this.resultCallback      = resultCallback;

            this.smtContextHandler = new SmtContextHandler(smtContextFactory);

            var rootPath = new Path(
                ImmutableArray <Path> .Empty,
                0,
                this.startingNode.Node,
                ImmutableArray <FlowEdge> .Empty);
            var rootState = new ExplorationState(
                rootPath,
                CallSiteStack.Empty,
                this.smtContextHandler.CreateEmptySolver(rootPath, this.startingNode, heapFactory));

            this.AddState(rootState);
        }
Example #2
0
        private static CallSiteStack GetNewCallSiteStack(ExplorationState currentState, FlowEdge edge)
        {
            CallSiteStack callSiteStack;

            if (edge.From is ReturnFlowNode)
            {
                Contract.Assert(edge is OuterFlowEdge);
                Contract.Assert(((OuterFlowEdge)edge).Kind == OuterFlowEdgeKind.Return);

                callSiteStack = currentState.CallSiteStack.Push((CallFlowNode)edge.To);
            }
            else if (edge.To is EnterFlowNode)
            {
                Contract.Assert(edge is OuterFlowEdge);
                Contract.Assert(((OuterFlowEdge)edge).Kind == OuterFlowEdgeKind.MethodCall);

                callSiteStack = currentState.CallSiteStack.IsEmpty ?
                                currentState.CallSiteStack : currentState.CallSiteStack.Pop();
            }
            else
            {
                callSiteStack = currentState.CallSiteStack;
            }

            return(callSiteStack);
        }
        public void Merge(ExplorationState state, SmtSolverHandler solverHandler)
        {
            Contract.Requires(state != null);
            Contract.Requires(solverHandler != null);
            Contract.Requires(state.Path.Node == this.Path.Node);
            Contract.Requires(state.CallSiteStack.Equals(this.CallSiteStack));

            this.Path = new Path(
                this.Path.Preceeding.AddRange(state.Path.Preceeding),
                Math.Max(this.Path.Depth, state.Path.Depth),
                this.Path.Node,
                this.Path.LeadingEdges.AddRange(state.Path.LeadingEdges));
            this.SolverHandler = solverHandler;
        }
Example #4
0
        // TODO: Divide into submethods to make more readable
        internal async Task <bool> ExploreAsync(CancellationToken cancelToken)
        {
            for (
                var currentState = this.ExplorationHeuristic.PickNextState();
                currentState != null;
                currentState = this.ExplorationHeuristic.PickNextState())
            {
                // TODO: Consider reusing the state instead of discarding
                this.RemoveState(currentState);

                IReadOnlyList <FlowEdge> edges;
                var currentNode   = currentState.Path.Node;
                var graphProvider = this.context.FlowGraphProvider;
                if (currentNode is EnterFlowNode)
                {
                    if (currentState.CallSiteStack == CallSiteStack.Empty)
                    {
                        edges = await graphProvider.GetCallEdgesToAsync((EnterFlowNode)currentNode);
                    }
                    else
                    {
                        // The execution is constrained by the call site on the stack
                        var edge = graphProvider.GetCallEdge(
                            currentState.CallSiteStack.CallSite,
                            (EnterFlowNode)currentNode);
                        edges = edge.ToSingular();
                    }
                }
                else if ((currentNode as CallFlowNode)?.Location.CanBeExplored == true &&
                         !(currentState.Path.Preceeding.FirstOrDefault()?.Node is EnterFlowNode))
                {
                    // If we can model the call and we haven't returned from that method yet
                    edges = await graphProvider.GetReturnEdgesToAsync((CallFlowNode)currentNode);
                }
                else
                {
                    edges = currentNode.IngoingEdges;
                }

                var toSolve = new List <ExplorationState>();

                int i = 0;
                foreach (bool doBranch in this.ExplorationHeuristic.DoBranch(currentState, edges))
                {
                    var edge = edges[i];
                    if (doBranch && this.IsEdgeAllowed(edge))
                    {
                        var branchedPath = new Path(
                            ImmutableArray.Create(currentState.Path),
                            currentState.Path.Depth + 1,
                            edge.From,
                            ImmutableArray.Create(edge));
                        CallSiteStack callSiteStack = GetNewCallSiteStack(currentState, edge);

                        var branchedState = new ExplorationState(
                            branchedPath,
                            callSiteStack,
                            currentState.SolverHandler);

                        bool wasMerged = false;
                        foreach (var mergeCandidate in this.statesOnLocations[branchedState.Path.Node].ToArray())
                        {
                            if (this.MergingHeuristic.DoMerge(branchedState, mergeCandidate))
                            {
                                SmtSolverHandler solverHandler;
                                if (branchedState.SolverHandler != mergeCandidate.SolverHandler)
                                {
                                    solverHandler = this.SmtHeuristic.SelectMergedSolverHandler(
                                        branchedState,
                                        mergeCandidate);
                                }
                                else
                                {
                                    solverHandler = branchedState.SolverHandler;
                                }

                                mergeCandidate.Merge(branchedState, solverHandler);
                                wasMerged = true;

                                break;
                            }
                        }

                        if (!wasMerged)
                        {
                            this.AddState(branchedState);
                        }

                        if (this.IsFinalState(branchedState) || this.SmtHeuristic.DoSolve(branchedState))
                        {
                            toSolve.Add(branchedState);
                        }
                    }
                    else
                    {
                        this.IsUnderapproximated = true;
                    }

                    i++;
                }

                if (toSolve.Count > 0)
                {
                    int j = 0;
                    foreach (bool doReuse in this.SmtHeuristic.DoReuse(currentState.SolverHandler, toSolve))
                    {
                        if (!doReuse)
                        {
                            toSolve[j].SolverHandler = currentState.SolverHandler.Clone();
                        }

                        j++;
                    }

                    foreach (var branchedState in toSolve)
                    {
                        var resultKind = branchedState.SolverHandler.Solve(branchedState.Path);
                        SolverCallCount++;

                        if (resultKind != ExplorationResultKind.Reachable || this.IsFinalState(branchedState))
                        {
                            this.RemoveState(branchedState);
                            var result = branchedState.SolverHandler.LastResult;
                            this.resultCallback(result);
                        }
                    }
                }

                // Check the cancellation before picking next node
                if (cancelToken.IsCancellationRequested)
                {
                    // It is an expected behaviour with well defined result, there is no need to throw an exception
                    break;
                }
            }

            // If there are any exploration states left, the results are not exhaustive
            return(this.States.Count == 0);
        }
Example #5
0
 private void RemoveState(ExplorationState state)
 {
     this.States.Remove(state);
     this.statesOnLocations[state.Path.Node].Remove(state);
 }
Example #6
0
 private void AddState(ExplorationState state)
 {
     this.States.Add(state);
     this.statesOnLocations[state.Path.Node].Add(state);
 }
Example #7
0
 private bool IsFinalState(ExplorationState branchedState)
 {
     return(branchedState.CallSiteStack == CallSiteStack.Empty &&
            this.finalNodeRecognizer.IsFinalNode(branchedState.Path.Node));
 }