private Expr CollectBooleanAssignment(IdentifierExpr glob, Variable assignedVar) { return(new NAryExpr(Token.NoToken, new FunctionCall(collectBoolFunc), new List <Expr>() { glob, IdentifierExpr.Ident(assignedVar) })); }
public void AbstractNonTaintedImplementations() { var impls = program.TopLevelDeclarations.OfType <Implementation>(); var taintedImpls = impls.Where(x => allDeps[x.Proc].Values.Any(d => Utils.VariableUtils.IsTainted(d)) ); var nonTaintedImpls = new HashSet <Implementation>(); if (false) { throw new NotImplementedException("Don't exercise abstraction as it causes mismatch of signatures on two sides"); //TODO: We get into parsing problems (print_tokens\(source,v2)) when one side is abstracted, and we get //different modsets later given the implementation for one and stub for another new HashSet <Implementation>(impls.Where(x => !taintedImpls.Contains(x))); //make a copy since topleveldecl changes nonTaintedImpls .Iter(x => { var modset = new VarSet(allDeps[x.Proc].ModSet()); Utils.VariableUtils.PruneLocals(x, modset); modset.RemoveWhere(v => x.Proc.OutParams.Contains(v)); x.Proc.Modifies = modset.Select(v => IdentifierExpr.Ident(v)).ToList(); Utils.DependenciesUtils.AddCalleeDependencySpecs(program, x.Proc, allDeps[x.Proc]); } ); Console.WriteLine("[Abstract non-taint] Abstracted {0} procedures [{1}]", nonTaintedImpls.Count(), String.Join(",", nonTaintedImpls.Select(x => x.Name))); } //get the number of tainted outputs (outputs whose summaries are potentially changed) var outvars = new List <Variable>(); var botTaintOutVars = new List <Variable>(); program.TopLevelDeclarations.OfType <Procedure>().Iter(x => { if (!allDeps.ContainsKey(x)) { return; } allDeps[x].Keys.Iter(y => outvars.Add(y)); var procBottomUpTaintVars = new List <Variable>(); allDeps[x].Keys.Where(k => allDeps[x][k].Contains(Utils.VariableUtils.BottomUpTaintVar)).Iter(y => procBottomUpTaintVars.Add(y)); botTaintOutVars.AddRange(procBottomUpTaintVars); //new: add an annotation to indicate that none of the variables are bottom up tainted var ens = new Ensures(true, (Expr)Expr.True); ens.Attributes = new QKeyValue(Token.NoToken, "bottomup_tainted_vars", procBottomUpTaintVars.Select(v => (object)v.Name).ToList(), null); x.Ensures.Add(ens); }); Console.WriteLine("#outputs with no bottomuptaint / #outputs = {0} / {1} ", outvars.Count - botTaintOutVars.Count, outvars.Count); //Do the removal after you are done with nonTaintedImpls, otherwise that becomes an empty set program.RemoveTopLevelDeclarations(x => nonTaintedImpls.Contains(x)); }
private Cmd InstrumentAssignCmd(AssignCmd assignCmd, Block enclBlock) { if (assignCmd.Lhss.Count > 1) { Console.WriteLine("Ignoring parallel assigns from statement taint {0}", assignCmd); return(null); } var assignedVar = assignCmd.Lhss[0].DeepAssignedVariable; var lhss = new List <AssignLhs>(); var rhss = new List <Expr>(); //lhs := rhs //out := if b_l then out else f(out, rhs) //lhs := upd(a, i, v) //out := if b_l then out else g(out, i, v) var glob = IdentifierExpr.Ident(globalCollectAssignmentsVar); var bConst = LookupOrCreateNewGuardConst(assignCmd, enclBlock); lhss.Add(new SimpleAssignLhs(Token.NoToken, glob)); Expr expr; var assignType = assignedVar.TypedIdent.Type; if (assignType.IsBool) { expr = CollectBooleanAssignment(glob, assignedVar); } else if (assignType.IsInt) { expr = CollectIntAssignment(glob, assignedVar); } else if (assignType.IsMap) { expr = CollectMapAssignment(glob, assignCmd.Rhss[0]); } else { Console.WriteLine("Skipping unexpected assignment during statement taint instrumentation {0}", assignCmd); return(null); } if (expr == null) { return(null); } var iteArgs = new List <Expr>() { IdentifierExpr.Ident(bConst), glob, expr }; rhss.Add(new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), iteArgs)); return(new AssignCmd(Token.NoToken, lhss, rhss)); }
private void CheckCandidateAssert(Constant c) { //TODO: generalize to allow multiple roots Debug.Assert(entryPoints.Count() == 1, "Currently only considering a single main in mergedProgram"); var expr = houdiniConsts .Where(y => y != c) .Aggregate((Expr)Expr.True, (x, y) => Expr.And(x, Expr.Not(IdentifierExpr.Ident(y)))); expr = Expr.And(expr, IdentifierExpr.Ident(c)); var axm = new Axiom(Token.NoToken, expr); mergedProg.AddTopLevelDeclaration(axm); InvokeCorralCommandLine(c); mergedProg.RemoveTopLevelDeclaration(axm); }
/// <summary> /// Returns a set {m_i, updateexpr_i} for all m_i that are updated /// </summary> /// <param name="map"></param> /// <param name="index"></param> /// <param name="value"></param> /// <param name="btype"></param> /// <returns></returns> private List <Tuple <IdentifierExpr, Expr> > VisitMapStore(IdentifierExpr mv, Expr index, Expr value) { //get AS set and ASFunc for this map. lookup by name //create m@1,.. //create n parallel assignments with 1 ite //m@1[index], m@2[index],.. = ite(AS(index,AS1), value, m@1[index]), ite(...),.. var aSites = currAllocSiteMapInfo.ContainsKey(index) ? currAllocSiteMapInfo[index] : (new HashSet <Expr>()); if (aSites.Count == 0) { //Case where AS(index) = {} var splitMapVar = GetOrCreateSplitMap(mv.Decl, SplitConsts.externalAlloc); return(new List <Tuple <IdentifierExpr, Expr> >() { Tuple.Create(IdentifierExpr.Ident(splitMapVar), value) }); } var btype = value.Type; if (btype == null) { Console.WriteLine("Stop here"); } Debug.Assert(btype != null); var iteArgs = new List <Tuple <IdentifierExpr, Expr> >(); //list of (mv', ite(cond,trueExpr,falseExpr)) tuples aSites .Iter(x => { var cond = Utils.DeclUtils.MkFuncApp(allocSiteFunc, new List <Expr>() { index, x }); //AS(index,AS1) var splitMapVar = GetOrCreateSplitMap(mv.Decl, x.ToString()); //m@AS1 var arg = Expr.Select(IdentifierExpr.Ident(splitMapVar), new Expr[] { index }); //m@AS1[index] if (arg.Type == null) { arg.Type = (splitMapVar.TypedIdent.Type as MapType).Result; //Console.WriteLine("Inserted missing type for mapselect expr {0}", arg); insertedTypeWarnings.Add(Tuple.Create((Expr)arg, "mapselect")); } Debug.Assert(arg.Type != null); var iteFunc = Utils.DeclUtils.MkOrGetFunc(prog, SplitConsts.iteFuncName, btype, new List <Microsoft.Boogie.Type>() { Microsoft.Boogie.Type.Bool, btype, btype }); var iteVal = Utils.DeclUtils.MkFuncApp(iteFunc, new List <Expr>() { (Expr)cond, value, (Expr)arg }); //ite(AS(index,AS1), value, m@AS1[index]) if (iteVal.Type == null) { //Console.WriteLine("Inserted missing type for ite expr {0}", iteVal); insertedTypeWarnings.Add(Tuple.Create((Expr)iteVal, "ite")); iteVal.Type = arg.Type; } iteArgs.Add(Tuple.Create(IdentifierExpr.Ident(splitMapVar), (Expr)iteVal)); } ); return(iteArgs); }
/// <summary> /// M := E /// </summary> /// <param name="lhs"></param> /// <param name="rhs"></param> /// <returns></returns> private AssignCmd VisitEntireMapAssignment(AssignLhs lhs, Expr rhs) { Debug.Assert(lhs.DeepAssignedVariable.TypedIdent.Type.IsMap); var ac = new AssignCmd(Token.NoToken, new List <AssignLhs>() { lhs }, new List <Expr>() { rhs }); //M := old(M) if (! (rhs is OldExpr && ((OldExpr)rhs).Expr is IdentifierExpr && ((IdentifierExpr)((OldExpr)rhs).Expr).Decl == lhs.DeepAssignedVariable) ) { Console.WriteLine("Don't handle direct stores M := e yet, found {0}", ac.ToString()); unhandledCommands.Add(ac); return(ac); } var splitVars = allAllocSites .Select(x => GetOrCreateSplitMap(lhs.DeepAssignedVariable, x)) .ToList(); ac.Lhss = splitVars.Select(x => (AssignLhs) new SimpleAssignLhs(Token.NoToken, IdentifierExpr.Ident(x))).ToList(); ac.Rhss = splitVars.Select(x => (Expr) new OldExpr(Token.NoToken, (Expr)IdentifierExpr.Ident(x))).ToList(); return(ac); }
private void CreateMainProcedure(Function reach) { //blocks List <Block> mainBlocks = new List <Block>(); List <Variable> locals = new List <Variable>(); HashSet <Constant> blockCallConsts = new HashSet <Constant>(); foreach (Implementation impl in prog.TopLevelDeclarations.Where(x => x is Implementation)) { // skip this impl if it is not marked as an entrypoint if (useProvidedEntryPoints && !QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "entrypoint")) { continue; } impl.Attributes = BoogieUtil.removeAttr("entrypoint", impl.Attributes); impl.Proc.Attributes = BoogieUtil.removeAttr("entrypoint", impl.Proc.Attributes); // skip initialization procedure if (QKeyValue.FindBoolAttribute(impl.Attributes, AvnAnnotations.InitialializationProcAttr) || QKeyValue.FindBoolAttribute(impl.Proc.Attributes, AvnAnnotations.InitialializationProcAttr)) { continue; } entrypoints.Add(impl.Name); //allocate params var args = new List <Variable>(); var rets = new List <Variable>(); impl.OutParams.ForEach(v => rets.Add(BoogieAstFactory.MkLocal(v.Name + "_" + impl.Name, v.TypedIdent.Type))); if (Options.allocateParameters) { // use impl.Proc here to pickup scalar/pointer attributes impl.Proc.InParams.ForEach(v => { var l = BoogieAstFactory.MkLocal(v.Name + "_" + impl.Name, v.TypedIdent.Type); // We are delibrately dropping the attributes so that // all parameters are initialized by allocation //l.Attributes = v.Attributes; args.Add(l); }); locals.AddRange(args); } else { impl.Proc.InParams.ForEach(v => { var g = BoogieAstFactory.MkGlobal(v.Name + "_" + impl.Name, v.TypedIdent.Type); //g.Attributes = v.Attributes; args.Add(g); }); globalParams.AddRange(args); } locals.AddRange(rets); //call var blockCallConst = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "__block_call_" + impl.Name, btype.Bool), false); blockCallConsts.Add(blockCallConst); blockEntryPointConstants[blockCallConst.Name] = impl.Name; impl2BlockingConstant[impl.Name] = blockCallConst; var blockCallAssumeCmd = new AssumeCmd(Token.NoToken, IdentifierExpr.Ident(blockCallConst)); var cmds = new List <Cmd>(); cmds.Add(blockCallAssumeCmd); if (Options.allocateParameters) // allocate parameters if option is enabled { var argMallocCmds = AllocatePointersAsUnknowns(args); cmds.AddRange(argMallocCmds); } // The beginning of an entry point must be reachable: assume reach(true); cmds.Add(new AssumeCmd(Token.NoToken, new NAryExpr(Token.NoToken, new FunctionCall(reach), new List <Expr> { Expr.True }))); var callCmd = new CallCmd(Token.NoToken, impl.Name, args.ConvertAll(x => (Expr)IdentifierExpr.Ident(x)), rets.ConvertAll(x => IdentifierExpr.Ident(x))); callCmd.Attributes = new QKeyValue(Token.NoToken, AvUtil.AvnAnnotations.AvhEntryPointAttr, new List <object>(), callCmd.Attributes); cmds.Add(callCmd); //succ var txCmd = new ReturnCmd(Token.NoToken); var blk = BoogieAstFactory.MkBlock(cmds, txCmd); mainBlocks.Add(blk); } foreach (Procedure proc in prog.TopLevelDeclarations.OfType <Procedure>()) { proc.Attributes = BoogieUtil.removeAttr("entrypoint", proc.Attributes); } // add global variables to prog // globals.Iter(x => prog.AddTopLevelDeclaration(x)); //add the constants to the prog blockCallConsts.Iter(x => prog.AddTopLevelDeclaration(x)); //TODO: get globals of type refs/pointers and maps var initCmd = (AssumeCmd)BoogieAstFactory.MkAssume(Expr.True); var globalCmds = new List <Cmd>() { initCmd }; //add call to corralExtraInit var init = Instrumentations.GetEnvironmentAssumptionsProc(prog); if (init != null && !Options.DelayInitialization) { globalCmds.Add(BoogieAstFactory.MkCall(init, new List <Expr>(), new List <Variable>())); } // Dont initialize Boogie instrumentation variables prog.GlobalVariables .Where(g => g.Name == "alloc" || BoogieUtil.checkAttrExists(AvnAnnotations.AllocatorVarAttr, g.Attributes)) .Where(g => !BoogieUtil.checkAttrExists("scalar", g.Attributes)) .Iter(g => g.AddAttribute("scalar")); // initialize globals prog.GlobalVariables .Where(g => g.Name != "alloc" && !BoogieUtil.checkAttrExists(AvnAnnotations.AllocatorVarAttr, g.Attributes)) .Iter(g => g.Attributes = BoogieUtil.removeAttrs(new HashSet <string> { "scalar", "pointer" }, g.Attributes)); globalCmds.AddRange(AllocatePointersAsUnknowns(prog.GlobalVariables.Select(x => (Variable)x).ToList())); if (init != null && Options.DelayInitialization) { globalCmds.Add(BoogieAstFactory.MkCall(init, new List <Expr>(), new List <Variable>())); } // globals for parameters prog.AddTopLevelDeclarations(globalParams); //first block var transferCmd = mainBlocks.Count > 0 ? (TransferCmd)(new GotoCmd(Token.NoToken, mainBlocks)) : (TransferCmd)(new ReturnCmd(Token.NoToken)); Block blkStart = new Block(Token.NoToken, "CorralMainStart", globalCmds, transferCmd); var blocks = new List <Block>(); blocks.Add(blkStart); blocks.AddRange(mainBlocks); var mainProcImpl = BoogieAstFactory.MkImpl(AvnAnnotations.CORRAL_MAIN_PROC, new List <Variable>(), new List <Variable>(), locals, blocks); mainProcImpl[0].AddAttribute("entrypoint"); prog.AddTopLevelDeclarations(mainProcImpl); }
//Change the body of any stub that returns a pointer into calling unknown() //TODO: only do this for procedures with a single return with a pointer type private void MkStubImplementation(List <Implementation> stubImpls, Procedure p) { List <Cmd> cmds = new List <Cmd>(); List <Variable> localVars = new List <Variable>(); stubs.Add(p.Name); foreach (var op in p.OutParams) { if (IsPointerVariable(op)) { cmds.Add(AllocatePointerAsUnknown(op)); } else { // Avoid using Havoc -- we'll let this fall on the floor as an // uninitialized variable. AVN will take care of concretizing it //cmds.Add(BoogieAstFactory.MkHavocVar(op)); } } foreach (var v in p.Modifies.Select(ie => ie.Decl)) { if (IsPointerVariable(v)) { cmds.Add(AllocatePointerAsUnknown(v)); } else { // unsupported Console.WriteLine("Warning: demonic havoc of global {0} in {1}", v.Name, p.Name); } } foreach (var ip in p.InParams) { if (!BoogieUtil.checkAttrExists("ref", ip.Attributes)) { continue; } string mapName = QKeyValue.FindStringAttribute(ip.Attributes, "ref"); if (mapName == null) { Utils.Print(String.Format("Expecting a map <name> with {:ref <name>} annotation on procedure {0}", p.Name), Utils.PRINT_TAG.AV_WARNING); continue; } var mapVars = prog.TopLevelDeclarations.OfType <Variable>().Where(x => x.Name == mapName && x.TypedIdent.Type.IsMap); if (mapVars.Count() != 1) { Utils.Print(String.Format("Mapname {0} provided in {{:ref}} for parameter {1} for procedure {2} has {3} matches, expecting exactly 1 match", mapName, ip.Name, p.Name, mapVars.Count()), Utils.PRINT_TAG.AV_WARNING); continue; } var tmpVar = BoogieAstFactory.MkLocal("__tmp_" + ip.Name, ip.TypedIdent.Type); localVars.Add(tmpVar); cmds.Add(AllocatePointerAsUnknown(tmpVar)); cmds.Add(BoogieAstFactory.MkMapAssign(mapVars.First(), IdentifierExpr.Ident(ip), IdentifierExpr.Ident(tmpVar))); } if (cmds.Count == 0) { return; //don't create a body if no statements } var blk = BoogieAstFactory.MkBlock(cmds, new ReturnCmd(Token.NoToken)); var blks = new List <Block>() { blk }; //don't insert the proc as it already exists var impl = BoogieAstFactory.MkImpl(p.Name, DropAnnotations(p.InParams), DropAnnotations(p.OutParams), new List <Variable>(), blks); ((Implementation)impl[1]).LocVars.AddRange(localVars); stubImpls.Add((Implementation)impl[1]); }