Exemplo n.º 1
0
        private void GenerateCorralHarnessForContract(ContractDefinition contract)
        {
            string harnessName              = "CorralEntry_" + contract.Name;
            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars = new List <BoogieVariable>
            {
                new BoogieLocalVariable(new BoogieTypedIdent("this", BoogieType.Ref)),
                new BoogieLocalVariable(new BoogieTypedIdent("msgsender_MSG", BoogieType.Ref)),
                new BoogieLocalVariable(new BoogieTypedIdent("msgvalue_MSG", BoogieType.Int)),
            };

            if (context.IsConstructorDefined(contract))
            {
                FunctionDefinition ctor = context.GetConstructorByContract(contract);
                localVars.AddRange(GetParamsOfFunction(ctor));
            }
            BoogieStmtList harnessBody = new BoogieStmtList();

            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            harnessBody.AddStatement(GenerateCorralWhileLoop(contract));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
Exemplo n.º 2
0
        private void GenerateBoogieHarnessForContract(ContractDefinition contract, Dictionary <int, BoogieExpr> houdiniVarMap)
        {
            string harnessName              = "BoogieEntry_" + contract.Name;
            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars   = CollectLocalVars(contract);
            BoogieStmtList        harnessBody = new BoogieStmtList();

            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            if (context.TranslateFlags.ModelReverts)
            {
                BoogieExpr assumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr("revert"));
                if (context.TranslateFlags.InstrumentGas)
                {
                    assumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, assumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
                }

                harnessBody.AddStatement(new BoogieAssumeCmd(assumePred));
            }
            harnessBody.AddStatement(GenerateWhileLoop(contract, houdiniVarMap, localVars));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
        //Create a contract boogie harness for each respective contract parsed through here.
        private void createContractBoogieHarness(ContractDefinition contract)
        {
            //create the contract harness name
            string contractHarnessName = "BoogieEntry_" + contract.Name;

            //input boogie variables
            List <BoogieVariable> inputParameters = new List <BoogieVariable>();
            //output boogie variables
            List <BoogieVariable> outputParameters = new List <BoogieVariable>();

            //Generate the harness procedure declaration.
            BoogieProcedure harnessProcedureDeclaration = new BoogieProcedure(contractHarnessName, inputParameters, outputParameters);

            classTranslatorContext.getProgram.AddBoogieDeclaration(harnessProcedureDeclaration);

            List <BoogieVariable> localVariables = Conversion_Utility_Tool.CollectLocalVars(new List <ContractDefinition>()
            {
                contract
            }, classTranslatorContext);
            BoogieStmtList harnessBody = new BoogieStmtList();

            //add dynamic type assumptions to harness body and generate constructor call fallback.
            harnessBody.AddStatement(BuildDynamicTypeAssumptions(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));

            //create a boogie implementation type that represents a harness with the above parameters
            BoogieImplementation harnessImpl = new BoogieImplementation(contractHarnessName, inputParameters, outputParameters, localVariables, harnessBody);

            //add the implementation as a declaration to the Boogie Program
            classTranslatorContext.getProgram.AddBoogieDeclaration(harnessImpl);
        }
Exemplo n.º 4
0
        public void Generate()
        {
            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("from", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("to", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("amount", BoogieType.Int))
            };
            List <BoogieVariable> outParams = new List <BoogieVariable>();

            List <BoogieAttribute> attributes = new List <BoogieAttribute>()
            {
                new BoogieAttribute("inline", 1),
            };
            var             procName  = "FallbackDispatch";
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.Program.AddDeclaration(procedure);

            List <BoogieVariable> localVars = new List <BoogieVariable>();
            BoogieStmtList        procBody  = GenerateBody(inParams);

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(implementation);

            // let us havoc all the global variables when fallback_unknowntype is called
            var             modSet        = context.Program.Declarations.Where(x => x is BoogieGlobalVariable).Select(x => (BoogieGlobalVariable)x).ToList();
            BoogieProcedure unknownFbProc = new BoogieProcedure("Fallback_UnknownType", inParams, outParams, attributes, modSet);

            context.Program.AddDeclaration(unknownFbProc);
        }
Exemplo n.º 5
0
        private void GenerateCorralChoiceProcForContract(ContractDefinition contract)
        {
            string procName = "CorralChoice_" + contract.Name;
            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("this", BoogieType.Ref)),
            };
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(procName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars = RemoveThisFromVariables(TransUtils.CollectLocalVars(new List <ContractDefinition>()
            {
                contract
            }, context));
            BoogieStmtList procBody = GenerateHavocBlock(contract, localVars);

            procBody.AddStatement(TransUtils.GenerateChoiceBlock(new List <ContractDefinition>()
            {
                contract
            }, context));
            BoogieImplementation procImpl = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(procImpl);
        }
Exemplo n.º 6
0
        private void GenerateCorralHarnessForContract(ContractDefinition contract)
        {
            string harnessName = "CorralEntry_" + contract.Name;

            if (context.TranslateFlags.CreateMainHarness && contract.Name.Equals(context.EntryPointContract))
            {
                harnessName = "main";
            }

            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars = new List <BoogieVariable>
            {
                new BoogieLocalVariable(new BoogieTypedIdent("this", BoogieType.Ref)),
                new BoogieLocalVariable(new BoogieTypedIdent("msgsender_MSG", BoogieType.Ref)),
                new BoogieLocalVariable(new BoogieTypedIdent("msgvalue_MSG", BoogieType.Int)),
            };

            if (context.IsConstructorDefined(contract))
            {
                FunctionDefinition ctor = context.GetConstructorByContract(contract);
                localVars.AddRange(GetParamsOfFunction(ctor));
            }
            BoogieStmtList harnessBody = new BoogieStmtList();

            //harnessBody.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr("this"), ));
            if (context.TranslateFlags.NoCustomTypes)
            {
                harnessBody.AddStatement((new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, new BoogieIdentifierExpr("null"), new BoogieLiteralExpr(0)))));
            }
            harnessBody.AddStatement(new BoogieCallCmd("FreshRefGenerator", new List <BoogieExpr>(), new List <BoogieIdentifierExpr>()
            {
                new BoogieIdentifierExpr("this")
            }));
            harnessBody.AddStatement(new BoogieAssumeCmd(new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("now"), new BoogieLiteralExpr(0))));
            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            if (context.TranslateFlags.ModelReverts)
            {
                BoogieExpr assumePred = new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr("revert"));
                if (context.TranslateFlags.InstrumentGas)
                {
                    assumePred = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.AND, assumePred, new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.GE, new BoogieIdentifierExpr("gas"), new BoogieLiteralExpr(0)));
                }

                harnessBody.AddStatement(new BoogieAssumeCmd(assumePred));
            }
            harnessBody.AddStatement(GenerateCorralWhileLoop(contract));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
Exemplo n.º 7
0
        public void Generate()
        {
            List <BoogieVariable> inParams = new List <BoogieVariable>()
            {
                new BoogieFormalParam(new BoogieTypedIdent("from", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("to", BoogieType.Ref)),
                new BoogieFormalParam(new BoogieTypedIdent("amount", BoogieType.Int))
            };
            List <BoogieVariable> outParams = new List <BoogieVariable>();

            List <BoogieAttribute> attributes = new List <BoogieAttribute>()
            {
                new BoogieAttribute("inline", 1),
            };
            var             procName  = "FallbackDispatch";
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.Program.AddDeclaration(procedure);

            List <BoogieVariable> localVars  = new List <BoogieVariable>();
            var            fbUnknownProcName = "Fallback_UnknownType";
            BoogieStmtList procBody          = GenerateBodyOfFallbackDispatch(inParams, fbUnknownProcName);

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(implementation);

            // let us havoc all the global variables when fallback_unknowntype is called
            var             modSet        = context.Program.Declarations.Where(x => x is BoogieGlobalVariable).Select(x => (BoogieGlobalVariable)x).ToList();
            BoogieProcedure unknownFbProc = new BoogieProcedure(fbUnknownProcName, inParams, outParams, attributes);

            context.Program.AddDeclaration(unknownFbProc);

            // we need to create an implementation as Corral seem to ignore modifies on declarations
            // https://github.com/boogie-org/corral/issues/98
            BoogieStmtList fbBody      = new BoogieStmtList();
            var            fbLocalVars = new List <BoogieVariable>();

            if (context.TranslateFlags.ModelStubsAsSkips() || context.TranslateFlags.ModelStubsAsCallbacks())
            {
                fbBody.AppendStmtList(CreateBodyOfUnknownFallback(fbLocalVars, inParams));
            }
            else
            {
                Debug.Assert(context.TranslateFlags.ModelStubsAsHavocs(), "Unknown option for modeling stubs");
                foreach (var global in modSet)
                {
                    fbBody.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(global.Name)));
                }
            }

            BoogieImplementation unknownFbImpl = new BoogieImplementation(fbUnknownProcName, inParams, outParams, fbLocalVars, fbBody);

            context.Program.AddDeclaration(unknownFbImpl);
        }
Exemplo n.º 8
0
 public void AddModiferToPostImpl(string modifier, BoogieImplementation procedure)
 {
     if (ModifierToBoogiePostImpl.ContainsKey(modifier))
     {
         throw new SystemException("duplicated modifier");
     }
     else
     {
         ModifierToBoogiePostImpl[modifier] = procedure;
     }
 }
Exemplo n.º 9
0
        private BoogieImplementation createSuccessImplementation(string name, BoogieImplementation originalImpl)
        {
            BoogieStmtList successStmtList = new BoogieStmtList();

            foreach (var cmd in originalImpl.StructuredStmts.BigBlocks[0].SimpleCmds)
            {
                generateRevertLogicForCmd(cmd, successStmtList, false, isHarnessProcudure(originalImpl.Name));
            }

            return(new BoogieImplementation(name, originalImpl.InParams, originalImpl.OutParams, originalImpl.LocalVars, successStmtList));
        }
Exemplo n.º 10
0
        private void GenerateGlobalProcedureAllocMany()
        {
            if (context.TranslateFlags.LazyNestedAlloc)
            {
                return;
            }

            // generate the internal one without base constructors
            string procName = "HavocAllocMany";
            List <BoogieVariable>  inParams   = new List <BoogieVariable>();
            List <BoogieVariable>  outParams  = new List <BoogieVariable>();
            List <BoogieAttribute> attributes = new List <BoogieAttribute>();

            if (context.TranslateFlags.GenerateInlineAttributes)
            {
                attributes.Add(new BoogieAttribute("inline", 1));
            }
            ;
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.Program.AddDeclaration(procedure);

            var oldAlloc = new BoogieLocalVariable(new BoogieTypedIdent("oldAlloc", new BoogieMapType(BoogieType.Ref, BoogieType.Bool)));
            List <BoogieVariable> localVars = new List <BoogieVariable>()
            {
                oldAlloc
            };
            BoogieStmtList       procBody          = new BoogieStmtList();
            BoogieIdentifierExpr oldAllocIdentExpr = new BoogieIdentifierExpr("oldAlloc");
            BoogieIdentifierExpr allocIdentExpr    = new BoogieIdentifierExpr("Alloc");

            // oldAlloc = Alloc
            procBody.AddStatement(new BoogieAssignCmd(oldAllocIdentExpr, allocIdentExpr));
            // havoc Alloc
            procBody.AddStatement(new BoogieHavocCmd(allocIdentExpr));
            // assume forall i:ref oldAlloc[i] ==> alloc[i]
            var             qVar              = QVarGenerator.NewQVar(0, 0);
            BoogieMapSelect allocMapSelect    = new BoogieMapSelect(allocIdentExpr, qVar);
            BoogieMapSelect oldAllocMapSelect = new BoogieMapSelect(oldAllocIdentExpr, qVar);
            BoogieExpr      allocAssumeExpr   = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.IMP, oldAllocMapSelect, allocMapSelect);

            procBody.AddStatement(new BoogieAssumeCmd(new BoogieQuantifiedExpr(true, new List <BoogieIdentifierExpr>()
            {
                qVar
            }, new List <BoogieType>()
            {
                BoogieType.Ref
            }, allocAssumeExpr)));

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(implementation);
        }
Exemplo n.º 11
0
        private BoogieImplementation createFailImplementation(string name, BoogieImplementation originalImpl)
        {
            Debug.Assert(!isHarnessProcudure(originalImpl.Name));

            BoogieStmtList failStmtList = new BoogieStmtList();

            foreach (var cmd in originalImpl.StructuredStmts.BigBlocks[0].SimpleCmds)
            {
                generateRevertLogicForCmd(cmd, failStmtList, true, false);
            }

            return(new BoogieImplementation(name, originalImpl.InParams, originalImpl.OutParams, originalImpl.LocalVars, failStmtList));
        }
Exemplo n.º 12
0
        //Generate Fresh Procedure Boogie Type and add as new reference to BoogieProgram
        private void BuildGlobalProcedureFresh()
        {
            // generate the internal one without base constructors
            string procName = "FreshRefGenerator";
            List <BoogieVariable> inParams = new List <BoogieVariable>();

            var outVar = new BoogieFormalParam(new BoogieTypedIdent("newRef", BoogieType.Ref));
            List <BoogieVariable> outParams = new List <BoogieVariable>()
            {
                outVar
            };
            List <BoogieAttribute> attributes = new List <BoogieAttribute>();

            if (Flags_HelperClass.GenerateInlineAttributes)
            {
                attributes.Add(new BoogieAttribute("inline", 1));
            }
            ;
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.getProgram.AddBoogieDeclaration(procedure);

            List <BoogieVariable> localVars = new List <BoogieVariable>();
            BoogieStmtList        procBody  = new BoogieStmtList();

            var outVarIdentifier = new BoogieIdentifierExpr("newRef");
            BoogieIdentifierExpr allocIdentExpr = new BoogieIdentifierExpr("Alloc");

            // havoc tmp;
            procBody.AddStatement(new BoogieHavocCmd(outVarIdentifier));
            // assume Alloc[tmp] == false;
            BoogieMapSelect allocMapSelect  = new BoogieMapSelect(allocIdentExpr, outVarIdentifier);
            BoogieExpr      allocAssumeExpr = new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.EQ, allocMapSelect, new BoogieLiteralExpr(false));

            procBody.AddStatement(new BoogieAssumeCmd(allocAssumeExpr));
            // Alloc[tmp] := true;
            procBody.AddStatement(new BoogieAssignCmd(allocMapSelect, new BoogieLiteralExpr(true)));
            // assume tmp != null
            procBody.AddStatement(new BoogieAssumeCmd(
                                      new BoogieBinaryOperation(BoogieBinaryOperation.Opcode.NEQ, outVarIdentifier, new BoogieIdentifierExpr("null"))));

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.getProgram.AddBoogieDeclaration(implementation);
        }
Exemplo n.º 13
0
        private void GenerateStructConstructors(ContractDefinition contract, StructDefinition structDefn)
        {
            // generate the internal one without base constructors
            string procName = structDefn.CanonicalName + "_ctor";
            List <BoogieVariable> inParams = new List <BoogieVariable>();

            inParams.AddRange(TransUtils.GetDefaultInParams());
            foreach (var member in structDefn.Members)
            {
                Debug.Assert(!member.TypeDescriptions.IsStruct(), "Do no handle nested structs yet!");
                var formalType = TransUtils.GetBoogieTypeFromSolidityTypeName(member.TypeName);
                var formalName = member.Name;
                inParams.Add(new BoogieFormalParam(new BoogieTypedIdent(formalName, formalType)));
            }

            List <BoogieVariable>  outParams  = new List <BoogieVariable>();
            List <BoogieAttribute> attributes = new List <BoogieAttribute>();

            if (context.TranslateFlags.GenerateInlineAttributes)
            {
                attributes.Add(new BoogieAttribute("inline", 1));
            }
            ;
            BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);

            context.Program.AddDeclaration(procedure);

            List <BoogieVariable> localVars = new List <BoogieVariable>();
            BoogieStmtList        procBody  = new BoogieStmtList();

            foreach (var member in structDefn.Members)
            {
                //f[this] = f_arg
                Debug.Assert(!member.TypeDescriptions.IsStruct(), "Do no handle nested structs yet!");
                var mapName       = member.Name + "_" + structDefn.CanonicalName;
                var formalName    = member.Name;
                var mapSelectExpr = new BoogieMapSelect(new BoogieIdentifierExpr(mapName), new BoogieIdentifierExpr("this"));
                procBody.AddStatement(new BoogieAssignCmd(mapSelectExpr, new BoogieIdentifierExpr(member.Name)));
            }

            BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, procBody);

            context.Program.AddDeclaration(implementation);
        }
Exemplo n.º 14
0
        private void GenerateBoogieHarnessForContract(ContractDefinition contract, Dictionary <int, BoogieExpr> houdiniVarMap)
        {
            string harnessName              = "BoogieEntry_" + contract.Name;
            List <BoogieVariable> inParams  = new List <BoogieVariable>();
            List <BoogieVariable> outParams = new List <BoogieVariable>();
            BoogieProcedure       harness   = new BoogieProcedure(harnessName, inParams, outParams);

            context.Program.AddDeclaration(harness);

            List <BoogieVariable> localVars   = CollectLocalVars(contract);
            BoogieStmtList        harnessBody = new BoogieStmtList();

            harnessBody.AddStatement(GenerateDynamicTypeAssumes(contract));
            GenerateConstructorCall(contract).ForEach(x => harnessBody.AddStatement(x));
            harnessBody.AddStatement(GenerateWhileLoop(contract, houdiniVarMap, localVars));
            BoogieImplementation harnessImpl = new BoogieImplementation(harnessName, inParams, outParams, localVars, harnessBody);

            context.Program.AddDeclaration(harnessImpl);
        }
Exemplo n.º 15
0
        public override bool Visit(ModifierDefinition modifier)
        {
            //if (modifier.Parameters.Length() > 0)
            //{
            //    throw new System.Exception("modifiers with parameters not implemented");
            //}
            var modifierInParams = TransUtils.GetDefaultInParams();

            foreach (var parameter in modifier.Parameters.Parameters)
            {
                string name = null;
                name = TransUtils.GetCanonicalLocalVariableName(parameter, context);
                BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(parameter.TypeName);
                modifierInParams.Add(new BoogieFormalParam(new BoogieTypedIdent(name, type)));
            }

            Block            body     = modifier.Body;
            bool             hasPre   = false;
            bool             hasPost  = false;
            List <Statement> postlude = new List <Statement>();

            // this list does not include locals introduced during translation
            List <BoogieLocalVariable> localVarsDeclared = new List <BoogieLocalVariable>();

            bool translatingPre = true;

            foreach (Statement statement in body.Statements)
            {
                if (statement is VariableDeclarationStatement varDecls)
                {
                    foreach (VariableDeclaration varDecl in varDecls.Declarations)
                    {
                        string     name = TransUtils.GetCanonicalLocalVariableName(varDecl, context);
                        BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(varDecl.TypeName);
                        // Issue a warning for intXX variables in case /useModularArithemtic option is used:
                        if (context.TranslateFlags.UseModularArithmetic && varDecl.TypeDescriptions.IsInt())
                        {
                            Console.WriteLine($"Warning: signed integer arithmetic is not handled with /useModularArithmetic option");
                        }
                        var boogieVariable = new BoogieLocalVariable(new BoogieTypedIdent(name, type));
                        if (translatingPre)
                        {
                            localVarsDeclared.Add(boogieVariable); // don't add locals after placeholder
                        }
                    }

                    // throw new System.Exception("locals within modifiers not supported");
                }
                if (statement is PlaceholderStatement)
                {
                    translatingPre = false;
                    // only capture those locals declared in the prefix, these are visible to postlude
                    context.AddPreludeLocalsToModifier(modifier.Name, localVarsDeclared);

                    continue;
                }
                if (translatingPre)
                {
                    hasPre = true;
                }
                else
                {
                    hasPost = true;
                }
            }

            var attributes = new List <BoogieAttribute>();

            attributes.Add(new BoogieAttribute("inline", 1));

            if (hasPre)
            {
                List <BoogieVariable> inParams  = new List <BoogieVariable>(modifierInParams);
                List <BoogieVariable> outParams = new List <BoogieVariable>();
                outParams.AddRange(localVarsDeclared.Select(x => new BoogieFormalParam(new BoogieTypedIdent("__out_mod_" + x.Name, x.TypedIdent.Type))));
                BoogieProcedure preludeProc = new BoogieProcedure(modifier.Name + "_pre", inParams, outParams, attributes);
                context.AddModiferToPreProc(modifier.Name, preludeProc);

                BoogieImplementation preludeImpl = new BoogieImplementation(modifier.Name + "_pre",
                                                                            inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList());
                context.AddModiferToPreImpl(modifier.Name, preludeImpl);
            }

            if (hasPost)
            {
                List <BoogieVariable> inParams = new List <BoogieVariable>(modifierInParams);
                inParams.AddRange(localVarsDeclared);
                List <BoogieVariable> outParams    = new List <BoogieVariable>();
                BoogieProcedure       postludeProc = new BoogieProcedure(modifier.Name + "_post", inParams, outParams, attributes);
                context.AddModiferToPostProc(modifier.Name, postludeProc);

                BoogieImplementation postludeImpl = new BoogieImplementation(modifier.Name + "_post",
                                                                             inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList());
                context.AddModiferToPostImpl(modifier.Name, postludeImpl);
            }

            return(false);
        }
Exemplo n.º 16
0
        public void Generate()
        {
            // Collect Global Variables.
            HashSet <BoogieGlobalVariable> globals = new HashSet <BoogieGlobalVariable>();

            foreach (var decl in context.Program.Declarations)
            {
                if (decl is BoogieGlobalVariable)
                {
                    var g = (BoogieGlobalVariable)decl;

                    if (mustHaveShadow(g.Name))
                    {
                        globals.Add(g);
                    }
                }
            }

            // Generate shadow state.
            foreach (var g in globals)
            {
                var varName = g.TypedIdent.Name;
                BoogieTypedIdent     shadowGlobal     = new BoogieTypedIdent("__tmp__" + varName, g.TypedIdent.Type);
                BoogieGlobalVariable shadowGlobalDecl = new BoogieGlobalVariable(shadowGlobal);

                context.Program.AddDeclaration(shadowGlobalDecl);
                shadowGlobals.Add(varName, shadowGlobalDecl);
            }

            // Duplicate and rename methods.
            Dictionary <string, BoogieImplementation> proceduresWithImpl = new Dictionary <string, BoogieImplementation>();

            procsWiltImplNames = proceduresWithImpl.Keys;
            foreach (var decl in context.Program.Declarations)
            {
                if (decl is BoogieImplementation)
                {
                    var boogieImpl = ((BoogieImplementation)decl);
                    if (proceduresInProgram.ContainsKey(boogieImpl.Name))
                    {
                        proceduresWithImpl.Add(boogieImpl.Name, boogieImpl);
                    }
                }
            }

            Dictionary <string, BoogieProcedure> failProcedures = new Dictionary <string, BoogieProcedure>();

            foreach (var implPair in proceduresWithImpl)
            {
                BoogieProcedure proc = proceduresInProgram[implPair.Key];

                if (isPublic(proc) || isConstructor(proc.Name))
                {
                    // If public maintain original definition as the wrapper.
                    BoogieProcedure successVersion = duplicateProcedure(proc, "success", true);
                    //BoogieImplementation successImpl = duplicateImplementation(implPair.Value, "success");

                    context.Program.AddDeclaration(successVersion);
                    //context.Program.AddDeclaration(successImpl);

                    BoogieProcedure failVersion = duplicateProcedure(proc, "fail", true);

                    context.Program.AddDeclaration(failVersion);

                    // Use original name of the procedure.
                    failProcedures.Add(implPair.Key, failVersion);
                }
                else if (!isHarnessProcudure(proc.Name))
                {
                    // Otherwise reuse original definition/impl as the "successful" method.
                    BoogieProcedure failVersion = duplicateProcedure(proc, "fail");

                    context.Program.AddDeclaration(failVersion);

                    // Use original name of the procedure.
                    failProcedures.Add(implPair.Key, failVersion);

                    // Reuse original node
                    proc.Name           = proc.Name + "__success";
                    implPair.Value.Name = implPair.Value.Name + "__success";
                }
            }

            // Create implementations for failing methods.
            foreach (var failProcedurePair in failProcedures)
            {
                string          originalProcName = failProcedurePair.Key;
                BoogieProcedure proc             = failProcedurePair.Value;

                var originalImpl = proceduresWithImpl[originalProcName];
                context.Program.AddDeclaration(createFailImplementation(proc.Name, originalImpl));
                context.Program.AddDeclaration(createSuccessImplementation(originalProcName + "__success", originalImpl));

                // Remove original implementation for non-public methods
                if (!isPublic(proceduresInProgram[originalProcName]) && !isConstructor(originalProcName))
                {
                    context.Program.Declarations.Remove(originalImpl);
                }
            }

            foreach (var implPair in proceduresWithImpl)
            {
                // Update non-public methods in harness methods
                if (isHarnessProcudure(implPair.Key))
                {
                    context.Program.AddDeclaration(createSuccessImplementation(implPair.Key, implPair.Value));

                    context.Program.Declarations.Remove(implPair.Value);
                }
            }

            // Create wrappers for public methods.

            foreach (var proc in proceduresInProgram.Values)
            {
                if (proceduresWithImpl.ContainsKey(proc.Name) && (isPublic(proc) || isConstructor(proc.Name)))
                {
                    BoogieImplementation impl = proceduresWithImpl[proc.Name];
                    impl.StructuredStmts = new BoogieStmtList();
                    impl.LocalVars       = new List <BoogieVariable>();

                    var exceptionVarName = "__exception";
                    var revertGlobalName = "revert";
                    impl.LocalVars.Add(new BoogieLocalVariable(new BoogieTypedIdent(exceptionVarName, BoogieType.Bool)));

                    var stmtList = impl.StructuredStmts;
                    stmtList.AddStatement(new BoogieHavocCmd(new BoogieIdentifierExpr(exceptionVarName)));
                    stmtList.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(revertGlobalName), new BoogieLiteralExpr(false)));

                    // Call Successful version.
                    BoogieStmtList successCallStmtList = new BoogieStmtList();
                    successCallStmtList.AddStatement(new BoogieCallCmd(impl.Name + "__success",
                                                                       impl.InParams.Select(inParam => (BoogieExpr) new BoogieIdentifierExpr(inParam.Name)).ToList(),
                                                                       impl.OutParams.Select(outParam => new BoogieIdentifierExpr(outParam.Name)).ToList()));
                    successCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieUnaryOperation(BoogieUnaryOperation.Opcode.NOT, new BoogieIdentifierExpr(revertGlobalName))));

                    // Call fail version.
                    BoogieStmtList failCallStmtList = new BoogieStmtList();
                    // Write global variables to temps
                    foreach (var shadowGlobalPair in shadowGlobals)
                    {
                        string origVarName = shadowGlobalPair.Key;
                        string shadowName  = shadowGlobalPair.Value.Name;
                        failCallStmtList.AddStatement(new BoogieAssignCmd(new BoogieIdentifierExpr(shadowName), new BoogieIdentifierExpr(origVarName)));
                    }
                    failCallStmtList.AddStatement(new BoogieCallCmd(impl.Name + "__fail",
                                                                    impl.InParams.Select(inParam => (BoogieExpr) new BoogieIdentifierExpr(inParam.Name)).ToList(),
                                                                    impl.OutParams.Select(outParam => new BoogieIdentifierExpr(outParam.Name)).ToList()));
                    failCallStmtList.AddStatement(new BoogieAssumeCmd(new BoogieIdentifierExpr(revertGlobalName)));

                    stmtList.AddStatement(new BoogieIfCmd(new BoogieIdentifierExpr(exceptionVarName), failCallStmtList, successCallStmtList));
                }
            }
        }
Exemplo n.º 17
0
        public override bool Visit(ModifierDefinition modifier)
        {
            //if (modifier.Parameters.Length() > 0)
            //{
            //    throw new System.Exception("modifiers with parameters not implemented");
            //}
            var modifierInParams = TransUtils.GetDefaultInParams();

            foreach (var parameter in modifier.Parameters.Parameters)
            {
                string name = null;
                name = TransUtils.GetCanonicalLocalVariableName(parameter);
                BoogieType type = TransUtils.GetBoogieTypeFromSolidityTypeName(parameter.TypeName);
                modifierInParams.Add(new BoogieFormalParam(new BoogieTypedIdent(name, type)));
            }

            Block            body     = modifier.Body;
            bool             hasPre   = false;
            bool             hasPost  = false;
            List <Statement> postlude = new List <Statement>();

            bool translatingPre = true;

            foreach (Statement statement in body.Statements)
            {
                if (statement is VariableDeclarationStatement)
                {
                    throw new System.Exception("locals within modifiers not supported");
                }
                if (statement is PlaceholderStatement)
                {
                    translatingPre = false;
                    continue;
                }
                if (translatingPre)
                {
                    hasPre = true;
                }
                else
                {
                    hasPost = true;
                }
            }

            if (hasPre)
            {
                List <BoogieVariable> inParams    = modifierInParams;
                List <BoogieVariable> outParams   = new List <BoogieVariable>();
                BoogieProcedure       preludeProc = new BoogieProcedure(modifier.Name + "_pre", inParams, outParams);
                context.AddModiferToPreProc(modifier.Name, preludeProc);

                BoogieImplementation preludeImpl = new BoogieImplementation(modifier.Name + "_pre",
                                                                            inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList());
                context.AddModiferToPreImpl(modifier.Name, preludeImpl);
            }

            if (hasPost)
            {
                List <BoogieVariable> inParams     = modifierInParams;
                List <BoogieVariable> outParams    = new List <BoogieVariable>();
                BoogieProcedure       postludeProc = new BoogieProcedure(modifier.Name + "_post", inParams, outParams);
                context.AddModiferToPostProc(modifier.Name, postludeProc);

                BoogieImplementation postludeImpl = new BoogieImplementation(modifier.Name + "_post",
                                                                             inParams, outParams, new List <BoogieVariable>(), new BoogieStmtList());
                context.AddModiferToPostImpl(modifier.Name, postludeImpl);
            }

            return(false);
        }