예제 #1
0
        public override Cmd VisitAssignCmd(AssignCmd node)
        {
            // gather state from all predecesors
            Block currBlock    = worklist.cmdBlocks[node];
            var   predTaintSet = worklist.GatherPredecessorsState(node, currBlock);
            var   taintSet     = new TaintSet(predTaintSet);

            // the assignment has the potential to cleanse the taint
            taintSet.RemoveWhere(v => node.Lhss.Exists(l => Utils.VariableUtils.ExtractVars(l).Contains(v)));

            if (changedProcs.Contains(nodeToImpl[node].Proc) || changedBlocks.Contains(currBlock) || // native taint
                InferDominatorTaint(currBlock))    // control taint
            {
                node.Lhss.Iter(lhs => taintSet.Add(Utils.VariableUtils.ExtractVars(lhs).First()));
            }
            else // data taint
            {
                for (int i = 0; i < node.Lhss.Count; ++i)
                {
                    var lhs     = Utils.VariableUtils.ExtractVars(node.Lhss[i]).First(); // TODO: stuff like: Mem_T.INT4[in_prio] := out_tempBoogie0
                    var rhsVars = Utils.VariableUtils.ExtractVars(node.Rhss[i]);
                    if (rhsVars.Intersect(predTaintSet).Count() > 0)                     // if RHS is tainted
                    {
                        taintSet.Add(lhs);                                               // so is LHS
                    }
                }
            }
            if (worklist.Assign(node, taintSet))
            {
                worklist.Propagate(node);
            }
            return(node);
        }
예제 #2
0
        public override Program VisitProgram(Program node)
        {
            //Console.WriteLine("Starting...");
            //Console.ReadLine();
            var orderedSCCs = CallGraphHelper.ComputeOrderedSCCs(callGraph);

            orderedSCCs.Reverse();
            int numVisited         = 0;
            ProcReadSetVisitor rsv = new ProcReadSetVisitor();

            foreach (var scc in orderedSCCs)
            {
                foreach (var proc in scc)
                {
                    var impl = node.Implementations.FirstOrDefault(i => i.Proc == proc);
                    if (impl == null)
                    {
                        continue;
                    }
                    //Console.Write("Visiting: {0} ({1}/{2}) [{3} cmds, {4} vars]", impl.Name, ++numVisited, program.Implementations.Count(), impl.Blocks.Sum(b => b.Cmds.Count + 1), impl.LocVars.Count);
                    Stopwatch        s    = Stopwatch.StartNew();
                    ManualResetEvent wait = new ManualResetEvent(false);
                    Thread           work = new Thread(new ThreadStart(() => { Visit(impl); wait.Set(); }));
                    work.Start();
                    Boolean signal = wait.WaitOne(timeOut);
                    s.Stop();
                    if (!signal)
                    {
                        work.Abort();
                        Console.WriteLine("Aborted due to timeout. Reverting to readSet");

                        // the worklist alg was interrupted, clear the worklist to be safe
                        worklist.workList.Clear();
                        worklist.stateSpace.Clear();
                        GC.Collect();

                        // compute the read set instead
                        rsv.currentProc = impl.Proc;
                        rsv.Visit(impl);

                        // turn it to dependencies (\forall r \in ReadSet: r <- ReadSet)
                        ProcDependencies[impl.Proc] = new Dependencies();
                        rsv.ProcReadSet[impl.Proc].Iter(r => ProcDependencies[impl.Proc][r] = rsv.ProcReadSet[impl.Proc]);
                        //ProcDependencies[impl.Proc].FixFormals(impl);
                    }
                    else
                    {
                        //Console.WriteLine(" {0} s", s.ElapsedMilliseconds / 1000.0);
                        // maintain the readSet (for cases where the analysis is too long and we revert to readset)
                        rsv.ProcReadSet[impl.Proc] = new VarSet();
                        rsv.ProcReadSet[impl.Proc].UnionWith(ProcDependencies[impl.Proc].Keys);
                        ProcDependencies[impl.Proc].Values.Iter(vs => rsv.ProcReadSet[impl.Proc].UnionWith(vs));
                    }
                }
                foreach (var proc in scc)
                {
                    var impl = node.Implementations.FirstOrDefault(i => i.Proc == proc);
                    if (impl == null)
                    {
                        continue;
                    }
                    Analysis.PopulateTaintLog(impl, Utils.ExtractTaint(this));
                }

                worklist.stateSpace.Clear();
                if (numVisited % 25 == 0)
                {
                    GC.Collect();
                }
            }

            // Removed. Printing directly to screen can be too huge.
            //ProcDependencies.Iter(pd => Console.Out.WriteLine(pd.Key + " : " + pd.Value));

            //node.Implementations.Iter(impl => Visit(impl));

            // compute top down taint
            orderedSCCs.Reverse();
            foreach (var scc in orderedSCCs)
            {
                //foreach (var proc in procEntryTDTaint.Keys)
                foreach (var proc in scc)
                {
                    if (!procEntryTDTaint.ContainsKey(proc))
                    {
                        continue;
                    }
                    var impl  = program.Implementations.Single(i => i.Proc == proc);
                    var entry = Utils.GetImplEntry(impl);
                    if (!worklist.stateSpace.ContainsKey(entry))
                    {
                        worklist.stateSpace[entry] = new Dependencies();
                    }
                    if (worklist.stateSpace[entry].JoinWith(procEntryTDTaint[impl.Proc]))
                    {
                        worklist.Propagate(entry);
                        Visit(impl);
                    }
                }
            }

            // the top down taint was removed from ProcDependencies so it won't flow up, so add it back in now
            procExitTDTaint.Iter(pd => ProcDependencies[pd.Key].JoinWith(pd.Value));

            // gathering the tainted scalar outputs for each procedure
            var taintedProcScalarOutputs = new Dictionary <Procedure, VarSet>();

            ProcDependencies.Iter(pd =>
            {
                var procedure    = pd.Key;
                var impl         = node.Implementations.FirstOrDefault(i => i.Proc == procedure);
                var dependencies = pd.Value;
                taintedProcScalarOutputs[procedure] = new VarSet();
                foreach (var r in impl.OutParams)
                {
                    if (r.TypedIdent.Type.IsInt && dependencies.ContainsKey(r) &&
                        (dependencies[r].Contains(Utils.VariableUtils.BottomUpTaintVar) || dependencies[r].Contains(Utils.VariableUtils.TopDownTaintVar)))
                    {
                        taintedProcScalarOutputs[procedure].Add(r);
                    }
                }
            });
            taintedProcScalarOutputs.Iter(t => Console.WriteLine("Tainted outputs for " + t.Key + " : " + t.Value));

            procEntryTDTaint.Iter(pd => Console.WriteLine("Tainted inputs/globals for " + pd.Key + " : " + pd.Value));

            // for now, before we finish running, we replace all implementation outputs with procedure outputs
            // TODO: in the future we should only use implementation inputs\outputs and lose the procedures overall
            ProcDependencies.Iter(pd =>
            {
                var impl = node.Implementations.FirstOrDefault(i => i.Proc == pd.Key);
                pd.Value.FixFormals(impl);
                foreach (var o in impl.OutParams)
                {
                    pd.Value.Remove(o);
                }
            });

            return(node);
        }