Example #1
0
        private SymbolicExpressionTracker <Variable, Expression> RenameInternal(Dictionary <Variable, FList <Variable> > renaming, Variable slackVar)
        {
            Contract.Requires(renaming != null);
            Contract.Ensures(Contract.Result <SymbolicExpressionTracker <Variable, Expression> >() != null);
            Contract.Ensures(renaming.Count == Contract.OldValue(renaming.Count));

            if (symbolicConditions.IsNormal())
            {
                renaming[slackVar] = FList <Variable> .Cons(slackVar, FList <Variable> .Empty);

                Set <Expression> result = new Set <Expression>();

                foreach (var exp in symbolicConditions.Values)
                {
                    result.AddIfNotNull(expressionRenamer(exp, renaming));
                }
                var renamedExpressions =
                    result.Count != 0 ?
                    new SetOfConstraints <Expression>(result, false) :
                    SetOfConstraints <Expression> .Unknown;

                renaming.Remove(slackVar);  // We should remove the slack variable!

                return(new SymbolicExpressionTracker <Variable, Expression>(this.slackVar, symbolicConditions));
            }
            else
            {
                return(this);
            }
        }
Example #2
0
 private static FList <string> AddExtraArgs(FList <string> args, string serviceAddress)
 {
     if (!String.IsNullOrWhiteSpace(serviceAddress) && serviceAddress != "*") // if not specified and not wildcard, use default address
     {
         args = args.Cons("-serviceAddress:" + serviceAddress);
     }
     return(args);
 }
Example #3
0
        /// <summary>
        /// Assumes that exception edges always target join points, so we never need to reach
        /// backwards across a throw edges.
        /// </summary>
        /// <param name="apc"></param>
        /// <param name="ifMissing"></param>
        /// <returns></returns>
        public AState /*?*/ GetPreState(APC apc, AState /*?*/ ifMissing, out bool noInfo)
        {
            // Find closest preceeding cached point
            // Keep a list of program points we visit backward so we can take the
            // same path forward.
            FList <APC> /*?*/ path = null;
            APC          current   = apc;
            APC          pred;
            AState /*?*/ state;
            bool         found;

            while (!(found = this.TryPreStateCache(current, out state)) && !RequiresJoining(current) && !this.CacheThisPC(current) && this.cfg.HasSinglePredecessor(current, out pred))
            {
                current = pred;
                path    = path.Cons(current);
            }
            if (!found)
            {
                noInfo = true;
                return(ifMissing); // unreachable
            }
            bool nonTrivialPath = path != null;

            // Now forward simulate and cache
            while (path != null)
            {
                if (IsBottom(path.Head, state))
                {
                    noInfo = true; // equate no info with bottom since we cannot manufacture bottom here
                    return(state);
                }
                // must get a mutable version if we are going to change it.
                state = MutableVersion(state, path.Head);
                state = Transfer(path.Head, state);
                if (IsBottom(path.Head, state))
                {
                    noInfo = false;
                    return(state);
                }
                path = path.Tail;
                if (path != null)
                {
                    // cache on next
                    this.CachePreState(path.Head, ImmutableVersion(state, path.Head));
                    // this.joinState.Add(path.Head, state);
                }
            }
            // cache on lookedup up apc
            if (nonTrivialPath)
            {
                this.CachePreState(apc, ImmutableVersion(state, apc));
                // this.joinState.Add(apc, state);
            }
            noInfo = false;
            return(state);
        }
Example #4
0
        private void AssignInParallel
            (WeakUpperBoundsEqual <Variable, Expression> wubeq, WeakUpperBounds <Variable, Expression> wub,
            Dictionary <Variable, FList <Variable> > sourcesToTargets, INumericalAbstractDomain <Variable, Expression> oracleDomain)
        {
            Contract.Requires(wubeq != null);
            Contract.Requires(wub != null);

            // adding the domain-generated variables to the map as identity
            var oldToNewMap = new Dictionary <Variable, FList <Variable> >(sourcesToTargets);

            if (!wubeq.IsTop)
            {
                foreach (var e in wubeq.SlackVariables)
                {
                    oldToNewMap[e] = FList <Variable> .Cons(e, FList <Variable> .Empty);
                }
            }

            if (!wub.IsTop)
            {
                foreach (var e in wub.SlackVariables)
                {
                    oldToNewMap[e] = FList <Variable> .Cons(e, FList <Variable> .Empty);
                }
            }

            // when x has several targets including itself, the canonical element shouldn't be itself
            foreach (var sourceToTargets in sourcesToTargets)
            {
                var source  = sourceToTargets.Key;
                var targets = sourceToTargets.Value;

                Contract.Assume(targets != null);

                if (targets.Length() > 1 && targets.Head.Equals(source))
                {
                    var tail = targets.Tail;
                    Contract.Assert(tail != null);

                    var newTargets = FList <Variable> .Cons(tail.Head, FList <Variable> .Cons(source, tail.Tail));

                    oldToNewMap[source] = newTargets;
                }
            }

            AssignInParallelWUBSpecific(wub, oldToNewMap);
            AssignInParallelWUBEQSpecific(wubeq, sourcesToTargets, oldToNewMap);
        }
        /// <summary>
        /// Given a method driver, compute a parallel renaming relation between the (symbolic) values at the return point
        /// of a method and those at the entry of the same method. This renaming relation will be used to map an abstract
        /// state at the end of one pass of analysis to the starting point of the next pass.
        ///
        /// Implementation is to use SymbolicValuesAt method to find symbolic values for "important" access pathes and
        /// match the symbolic values that represent the same access path.
        /// </summary>
        /// <param name="driver"></param>
        /// <returns></returns>
        IFunctionalMap <Variable, FList <Variable> > GetFieldMapping(IMethodDriver <Local, Parameter, Method, Field, Property, Event, Type, Attribute, Assembly, Expression, Variable, ILogOptions>
                                                                     driver, APC pc1, APC pc2)
        {
            FunctionalMap <Variable, FList <Variable> > fieldMapping = null;

            fieldMapping = FunctionalMap <Variable, FList <Variable> > .Empty;
            foreach (Pair <string, Variable> pair in SymbolicValuesAt(pc1, driver))
            {
                if (!fieldMapping.Contains(pair.Two))
                {
                    fieldMapping = (FunctionalMap <Variable, FList <Variable> >)fieldMapping.Add(pair.Two, FList <Variable> .Empty);
                }
                foreach (Pair <string, Variable> pair2 in SymbolicValuesAt(pc2, driver))
                {
                    if (pair.One == pair2.One)
                    {
                        FList <Variable> list = fieldMapping[pair.Two];
                        list         = list.Cons(pair2.Two);
                        fieldMapping = (FunctionalMap <Variable, FList <Variable> >)fieldMapping.Add(pair.Two, list);
                    }
                }
            }
            return(fieldMapping);
        }
Example #6
0
 public static void Push <Arg0, Arg1, Arg2, Arg3, TResult>(Func <Func <Arg0, Arg1, Arg2, Arg3, TResult>, Arg0, Arg1, Arg2, Arg3, TResult> adapter)
 {
     currentCallAdapters = currentCallAdapters.Cons(adapter);
 }
Example #7
0
        private static FList <IOperationExceptionInformation> PopPushHandlers(BasicBlock block, FList <IOperationExceptionInformation> currentHandlers, IOperationExceptionInformation[] handlers, ref FList <IOperationExceptionInformation> containingHandlers)
        {
            Contract.Requires(block != null);
            Contract.Requires(handlers != null);
            Contract.Requires(Contract.ForAll(handlers, h => h != null));

            // pop fault/finally subroutines off subroutine stack whose scope ends here
            var blockOffset = block.Offset;

            #region Pop protecting handlers off stack whose scope ends here
            for (int i = 0; i < handlers.Length; i++)
            {
                if (handlers[i].TryEndOffset == blockOffset)
                {
                    // must be head
                    if (currentHandlers != null && Object.Equals(handlers[i], currentHandlers.Head))
                    {
                        currentHandlers = currentHandlers.Tail;
                    }
                    else
                    {
                        throw new ApplicationException("bad order of handlers");
                    }
                }
            }
            #endregion

            #region Push protecting handlers on stack whose scope starts here

            // reverse order
            for (int i = handlers.Length - 1; i >= 0; i--)
            {
                if (handlers[i].TryStartOffset == blockOffset)
                {
                    // push this handler on top of current block enclosing handlers
                    currentHandlers = FList <IOperationExceptionInformation> .Cons(handlers[i], currentHandlers); // Push handler
                }
            }
            #endregion

            #region Pop containing handlers off containing handler stack whose scope ends here
            for (int i = 0; i < handlers.Length; i++)
            {
                if (handlers[i].HandlerEndOffset == blockOffset)
                {
                    // must be head
                    if (containingHandlers != null && Object.Equals(handlers[i], containingHandlers.Head))
                    {
                        containingHandlers = containingHandlers.Tail;
                    }
                    else
                    {
                        throw new ApplicationException("bad order of handlers");
                    }
                }
            }
            #endregion

            #region Push containing handler on stack whose scope starts here

            // reverse order
            for (int i = handlers.Length - 1; i >= 0; i--)
            {
                if (handlers[i].HandlerStartOffset == blockOffset)
                {
                    // push this handler on top of containing handlers
                    containingHandlers = FList <IOperationExceptionInformation> .Cons(handlers[i], containingHandlers); // Push handler
                }
            }
            #endregion


            // record handlers for this block
            block.Handlers = currentHandlers;

            block.ContainingHandler = (containingHandlers != null) ? containingHandlers.Head : null;

            return(currentHandlers);
        }
Example #8
0
 private void AddUpdate(Update upd)
 {
     Debug.Assert(!this.IsConstant, "modification of locked down egraph");
     this.updates = FList.Cons(upd, this.updates);
 }
Example #9
0
        /// <summary>
        /// Compute a pre order (ignoring back edges) of the CFG reachable from the entry node
        ///
        /// As a side effect, assigns each block its DF finishing number.
        /// </summary>
        public static FList /*<BasicBlocks>*/ Compute(ControlFlowGraph cfg)
        {
            // depth-first search

            bool[] markBit = new bool[cfg.BlockCount];

            FList result = null;
            int   DFTime = 0;

            // Use a stack to represent the state of the search.
            // Each stack element consists of a basic block and the
            // the index of the next successor of that block to process.

            Stack stack = new Stack();

            CfgBlock[] blocks = cfg.Blocks();

            CfgBlock start = cfg.Entry;

            // invariant: all blocks pushed on the stack are marked.
            markBit[start.Index] = true;
            stack.Push(new StackElem(start));
            while (stack.Count > 0)
            {
                StackElem  elem             = (StackElem)stack.Peek();
                CfgBlock   b                = elem.node;
                int        nextChild        = elem.nextChild;
                CfgBlock[] normalNodes      = cfg.NormalSucc(b);
                CfgBlock[] exnNodes         = cfg.ExcpSucc(b);
                int        normalNodesCount = normalNodes.Length;
                int        exnNodesCount    = exnNodes.Length;
                // Is there another child to process?
                if (nextChild < normalNodesCount + exnNodesCount)
                {
                    // Figure out the actual block.
                    CfgBlock child;
                    if (nextChild < normalNodesCount)
                    {
                        child = normalNodes[nextChild];
                    }
                    else
                    {
                        child = exnNodes[nextChild - normalNodesCount];
                    }
                    elem.nextChild = nextChild + 1;
                    // push the child block on to the stack.
                    if (!markBit[child.Index])
                    {
                        markBit[child.Index] = true;
                        stack.Push(new StackElem(child));
                    }
                }
                else
                {
                    // After all children are processed, place the block
                    // on the result.
                    stack.Pop();
                    b.priority = ++DFTime;
                    result     = FList.Cons(b, result);
                }
            }
            return(result);
        }