예제 #1
0
        private static void RunReadSetAnalysis(Program program, ProcReadSetVisitor rsVisitor, DependencyVisitor depVisitor = null)
        {
            rsVisitor.Visit(program);
            // prune
            if (Prune)
            {
                rsVisitor.ProcReadSet.Keys.Iter(p => Utils.VariableUtils.PruneLocals(program.Implementations.SingleOrDefault(i => i.Proc.Name == p.Name), rsVisitor.ProcReadSet[p]));
            }

            // create a dependency set \foreach r \in ReadSet: r <- ReadSet
            Dictionary <Procedure, Dependencies> rsProcDeps = new Dictionary <Procedure, Dependencies>();

            rsVisitor.ProcReadSet.Keys.Iter(p => { rsProcDeps[p] = new Dependencies(); rsVisitor.ProcReadSet[p].Iter(r => rsProcDeps[p][r] = rsVisitor.ProcReadSet[p]); });

            // print
            program.Implementations.Iter(impl => PopulateDependencyLog(impl, rsProcDeps[impl.Proc], Utils.StatisticsHelper.ReadSet));

            // taint
            if (changeLog.Count > 0)
            {
                depVisitor.ProcDependencies = rsProcDeps;
                depVisitor.Visit(program); // reminder: taint is essentially a dependecy analysis
                // extract taint from dependencies and print
                program.Implementations.Iter(impl => PopulateTaintLog(impl, Utils.ExtractTaint(depVisitor)));
                // remove the special taint var
                rsProcDeps.Values.Iter(dep => dep.Values.Iter(d => { d.Remove(Utils.VariableUtils.BottomUpTaintVar); d.Remove(Utils.VariableUtils.TopDownTaintVar); }));
            }

            // stats
            if (PrintStats)
            {
                rsVisitor.ProcReadSet.Iter(prs =>
                {
                    var proc = prs.Key; var readSet = prs.Value;
                    var impl = program.Implementations.SingleOrDefault(i => i.Proc.Name == proc.Name);
                    if (impl != null) // conservatively each output\global is dependent on all of the readset
                    {
                        readSet.Where(v => v is GlobalVariable || impl.OutParams.Contains(v) ||
                                      /* just to be safe: */ proc.OutParams.Contains(v)).Iter(v => PopulateStatsLog(Utils.StatisticsHelper.ReadSet, impl, v, readSet));
                    }
                });
            }
        }
예제 #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);
        }
예제 #3
0
        private static void RunAnalysis(string filename, Program program)
        {
            var dataDepVisitor = new DependencyVisitor(filename, program, changeLog, Timeout, Prune, true);
            var dataDeps       = dataDepVisitor.ProcDependencies;

            if (Refine || BothDependencies || DataOnly)
            {
                RunDependencyAnalysis(program, dataDepVisitor, Utils.StatisticsHelper.DataOnly, DataOnly);
                if (DataOnly)
                {
                    return;
                }
            }

            dataDepVisitor.worklist.stateSpace.Clear(); // helping the garbage collector
            GC.Collect();

            var allDepVisitor = new DependencyVisitor(filename, program, changeLog, Timeout, Prune, DataOnly);
            var allDeps       = allDepVisitor.ProcDependencies;

            if (Refine || !ReadSet)
            {
                RunDependencyAnalysis(program, allDepVisitor, Utils.StatisticsHelper.DataAndControl, !ReadSet); // !ReadSet in the case we want to compute taint using the read set as the baseline dependency
            }
            //// test SB deps
            //Random rnd = new Random();
            //foreach (var impl in program.Implementations)
            //{
            //    Console.WriteLine("Deps[" + impl + "] = " + allDeps[impl.Proc]);
            //    Console.WriteLine("Superblock = " + Utils.DependenciesUtils.SuperBlockDependencies(impl.Blocks, allDepVisitor.worklist.stateSpace[impl.Blocks.Last().TransferCmd], allDeps));
            //    int start = rnd.Next(0, impl.Blocks.Count);
            //    int num = rnd.Next(1, impl.Blocks.Count - start);
            //    var superBlock = impl.Blocks.GetRange(start, num);
            //    var exitBlock = superBlock.Last();
            //    if (!allDepVisitor.worklist.stateSpace.ContainsKey(exitBlock.TransferCmd))
            //    {
            //        Console.WriteLine("Block " + impl.Blocks[start + num] + " not in statspace");
            //        Debug.Assert(false);
            //    }
            //    var deps = Utils.DependenciesUtils.SuperBlockDependencies(superBlock, allDepVisitor.worklist.stateSpace[exitBlock.TransferCmd], allDeps);
            //    Console.Write("Deps for [");
            //    impl.Blocks.GetRange(start, num).Iter(b => Console.Write(b + ","));
            //    Console.Write("]:");
            //    Console.WriteLine(deps);
            //}

            allDepVisitor.worklist.stateSpace.Clear(); // helping the garbage collector
            GC.Collect();

            #region Control+Data dependencies must contain the Data dependencies
            Debug.Assert(dataDeps.All(pd => {
                var proc = pd.Key; var ddeps = pd.Value; var adeps = allDeps[proc];
                return(ddeps.Keys.All(v => {
                    if (!adeps.Keys.Contains(v))
                    {
                        Console.WriteLine("{2}: {0} not contained in {1}", v, adeps.ToString(), proc);
                        return false;
                    }
                    if (!adeps[v].IsSupersetOf(ddeps[v]))
                    {
                        Console.WriteLine("{3}: {0} not superset of {1} for {2}", adeps.ToString(), ddeps.ToString(), v, proc);
                        return false;
                    }
                    return true;
                }));
            }));
            #endregion


            //output dependency in a bpl file
            if (AnnotateDependencies)
            {
                Utils.DependenciesUtils.PruneProcDependencies(program, allDeps); //for now we prune it
                (new DependencyWriter(program, allDeps, allDepVisitor.procEntryTDTaint, allDepVisitor.procExitTDTaint)).Visit(program);
                var depFileName = filename + "_w_dep.bpl";
                Utils.PrintProgram(program, depFileName);
                Console.WriteLine("Adding dependencies to program to {0}", depFileName);
                return;
            }

            ProcReadSetVisitor rsVisitor = new ProcReadSetVisitor();
            if (ReadSet)
            {
                RunReadSetAnalysis(program, rsVisitor, new DependencyVisitor(filename, program, changeLog, Timeout, Prune, DataOnly));
                #region ReadSet must contain the Control+Data dependencies
                Debug.Assert(rsVisitor.ProcReadSet.All(prs =>
                {
                    var proc = prs.Key; var readSet = prs.Value;
                    if (!allDeps.ContainsKey(proc))
                    {
                        return(true);
                    }
                    var deps = allDeps[proc];
                    return(deps.Keys.All(v => {
                        if (!(readSet.Contains(v) && readSet.IsSupersetOf(deps[v])))
                        {
                            Console.WriteLine("Failed for " + v + " in proc " + proc);
                            Console.WriteLine("RS:");
                            readSet.Iter(r => Console.WriteLine(" " + r));
                            Console.WriteLine("Deps[" + v + "]:");
                            deps[v].Iter(r => Console.WriteLine(" " + r));

                            return false;
                        }
                        return true;
                    }));
                }));
                #endregion
            }


            if (Refine)
            {
                RunRefinedDepAnalysis(filename, program, dataDeps, allDeps);
            }

            // TODO: create tainted blocks and block dependencies
            if (AbstractNonTainted)
            {
                throw new NotImplementedException("AbstractNonTainted is not tested currently");
                Utils.DependenciesUtils.PruneProcDependencies(program, allDeps); //for now we prune it
                var antc = new AbstractNonTaintProgram(program, allDeps, null, null);
                antc.AbstractNonTaintedImplementations();
                var absFilename = filename + ".taintAbstract.bpl";
                Utils.PrintProgram(program, absFilename);
                Console.WriteLine("Printing non-taint abstracted program to {0}", absFilename);
            }

            //Refined statement taint
            if (RefinedStmtTaintAnalysis)
            {
                //TODO: pass the modified set of methods
                (new RefinedStmtTaintInstrumentation(program, new HashSet <Implementation>())).Instrument();
                var outFile = filename.Replace(".bpl", "") + "_stmtTaintInstr.bpl";
                Utils.PrintProgram(program, outFile);
                Console.WriteLine("Printing stmt taint instrumented program to {0}", outFile);
            }
        }