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); }
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); }