示例#1
0
        public bool SolveBlock(Block source, Block block)
        {
            this.block = block;

            if (!block.LastInstr.IsConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch)
            {
                return(false);
            }

            ctx = new Context();

            CflowTranslatorCtx translator = this.TranslatorInit(source == block && !(source.Parent is HandlerBlock));

            var instructions = block.Instructions;

            if (instructions.Count == 0)
            {
                return(false);
            }

            try
            {
                for (int i = 0; i < instructions.Count - 1; i++)
                {
                    var instr = instructions[i].Instruction;
                    TranslateInstruction(translator, instr);
                }
            }
            catch (NullReferenceException)
            {
                return(false);
            }

            return(TranslateBranch(translator));
        }
示例#2
0
        private CflowTranslatorCtx TranslatorInit(bool fromFirstBlock)
        {
            ParameterList methodParameters = this.blocks.Method.Parameters;
            LocalList     methodLocals     = this.blocks.Method.Body.Variables;

            CflowTranslatorCtx translator = new CflowTranslatorCtx(ctx, new CflowStack(), new List <BitVecExpr>(), new List <BitVecExpr>());

            for (int i = 0; i < methodParameters.Count; i++)
            {
                translator.Args.Add(ctx.MkBVConst("Arg" + i.ToString(), 32));
            }

            for (int i = 0; i < methodLocals.Count; i++)
            {
                if (fromFirstBlock)
                {
                    translator.Locals.Add(ctx.MkBV(0, 32));
                }
                else
                {
                    translator.Locals.Add(ctx.MkBVConst("Loc" + i.ToString(), 32));
                }
            }

            return(translator);
        }
示例#3
0
        public bool TranslateBranch(CflowTranslatorCtx translator)
        {
            var         stack = translator.Stack;
            Instruction instr = block.LastInstr.Instruction;

            switch (instr.OpCode.Code)
            {
            case Code.Beq:
            case Code.Beq_S: return(Solve_Beq(stack));

            case Code.Bge:
            case Code.Bge_S: return(Solve_Bge(stack));

            case Code.Bge_Un:
            case Code.Bge_Un_S: return(Solve_Bge_Un(stack));

            case Code.Bgt:
            case Code.Bgt_S: return(Solve_Bgt(stack));

            case Code.Bgt_Un:
            case Code.Bgt_Un_S: return(Solve_Bgt_Un(stack));

            case Code.Ble:
            case Code.Ble_S: return(Solve_Ble(stack));

            case Code.Ble_Un:
            case Code.Ble_Un_S: return(Solve_Ble_Un(stack));

            case Code.Blt:
            case Code.Blt_S: return(Solve_Blt(stack));

            case Code.Blt_Un:
            case Code.Blt_Un_S: return(Solve_Blt_Un(stack));

            case Code.Bne_Un:
            case Code.Bne_Un_S: return(Solve_Bne_Un(stack));

            case Code.Brfalse:
            case Code.Brfalse_S: return(Solve_Brfalse(stack));

            case Code.Brtrue:
            case Code.Brtrue_S: return(Solve_Brtrue(stack));

            case Code.Switch: return(Solve_Switch(stack));

            default:
                return(false);
            }
        }
示例#4
0
        private bool Solve_Switch(CflowStack stack)
        {
            Block        target;
            List <Block> targets;
            bool         modified = false;
            int          index;

            var val1 = stack.Pop();

            if (val1 is BitVecExpr && (val1 as BitVecExpr).Simplify().IsNumeral != true)
            {
                var cfg = CflowCFG.ControlFlow;

                foreach (List <Block> list in cfg)
                {
                    token.ThrowIfCancellationRequested();

                    CflowTranslatorCtx translator = TranslatorInit(true);

                    List <Instr> instructions = new List <Instr>();

                    foreach (Block b in list)
                    {
                        instructions.AddRange(b.Instructions);
                    }

                    for (int i = 0; i < instructions.Count - 1; i++)
                    {
                        var instr = instructions[i].Instruction;
                        TranslateInstruction(translator, instr);
                    }

                    object val2 = translator.Stack.Pop();

                    if (val2 is BitVecExpr && (val2 as BitVecExpr).Simplify().IsNumeral == true)
                    {
                        this.BifurcateBlocks(cfg, list);

                        if (!int.TryParse((val2 as BitVecExpr).Simplify().ToString(), out index))
                        {
                            index = -1;
                        }

                        var beforeSwitch = list[list.Count - 2];

                        if (beforeSwitch.LastInstr.IsConditionalBranch())
                        {
                            var newBlock = new Block();

                            for (int i = 0; i < list.Last().Instructions.Count - 1; i++)
                            {
                                var instr = list.Last().Instructions[i];
                                if (instr.OpCode != OpCodes.Nop)
                                {
                                    newBlock.Instructions.Add(true ? new Instr(instr.Instruction.Clone()) : instr);
                                }
                            }

                            newBlock.Insert(newBlock.Instructions.Count, OpCodes.Pop.ToInstruction()); // for switch

                            if (beforeSwitch.FallThrough != null && beforeSwitch.FallThrough == list.Last())
                            {
                                targets = block.Targets;
                                if (targets == null || index < 0 || index >= targets.Count)
                                {
                                    target = block.FallThrough;
                                }
                                else
                                {
                                    target = targets[index];
                                }

                                beforeSwitch.FallThrough.Parent.Add(newBlock);
                                beforeSwitch.SetNewFallThrough(newBlock);
                                newBlock.SetNewFallThrough(target);
                                modified = true;
                            }

                            if (beforeSwitch.Targets != null && beforeSwitch.Targets[0] == list.Last())
                            {
                                targets = block.Targets;
                                if (targets == null || index < 0 || index >= targets.Count)
                                {
                                    target = block.FallThrough;
                                }
                                else
                                {
                                    target = targets[index];
                                }

                                beforeSwitch.FallThrough.Parent.Add(newBlock);
                                beforeSwitch.SetNewTarget(0, newBlock);
                                newBlock.SetNewFallThrough(target);
                                modified = true;
                            }
                        }
                        else if (beforeSwitch.LastInstr.OpCode.Code == Code.Switch)
                        {
                            //just skip
                        }
                        else
                        {
                            var newBlock = new Block();

                            for (int i = 0; i < list.Last().Instructions.Count - 1; i++)
                            {
                                var instr = list.Last().Instructions[i];
                                if (instr.OpCode != OpCodes.Nop)
                                {
                                    newBlock.Instructions.Add(true ? new Instr(instr.Instruction.Clone()) : instr);
                                }
                            }

                            newBlock.Insert(newBlock.Instructions.Count, OpCodes.Pop.ToInstruction()); // for switch

                            targets = block.Targets;
                            if (targets == null || index < 0 || index >= targets.Count)
                            {
                                target = block.FallThrough;
                            }
                            else
                            {
                                target = targets[index];
                            }

                            beforeSwitch.FallThrough.Parent.Add(newBlock);
                            beforeSwitch.SetNewFallThrough(newBlock);
                            newBlock.SetNewFallThrough(target);
                            modified = true;
                        }

                        if (modified == true)
                        {
                            break;
                        }
                    }
                }

                return(modified);
            }
            else if (val1 is BitVecExpr)
            {
                index = int.Parse((val1 as BitVecExpr).Simplify().ToString());

                targets = block.Targets;
                if (targets == null || index < 0 || index >= targets.Count)
                {
                    target = block.FallThrough;
                }
                else
                {
                    target = targets[index];
                }

                block.Insert(block.Instructions.Count - 1, OpCodes.Pop.ToInstruction());

                block.ReplaceSwitchWithBranch(target);

                return(true);
            }

            return(false);
        }
示例#5
0
        public void TranslateInstruction(CflowTranslatorCtx translator, Instruction instr)
        {
            var stack  = translator.Stack;
            var args   = translator.Args;
            var locals = translator.Locals;

            switch (instr.OpCode.Code)
            {
            case Code.Starg:
            case Code.Starg_S: Translate_Starg(stack, args, (Parameter)instr.Operand); break;

            case Code.Stloc:
            case Code.Stloc_S: Translate_Stloc(stack, locals, (Local)instr.Operand); break;

            case Code.Stloc_0: Translate_Stloc(stack, locals, 0); break;

            case Code.Stloc_1: Translate_Stloc(stack, locals, 1); break;

            case Code.Stloc_2: Translate_Stloc(stack, locals, 2); break;

            case Code.Stloc_3: Translate_Stloc(stack, locals, 3); break;

            case Code.Ldarg:
            case Code.Ldarg_S: stack.Push(GetArg(stack, args, (Parameter)instr.Operand)); break;

            case Code.Ldarg_0: stack.Push(GetArg(stack, args, 0)); break;

            case Code.Ldarg_1: stack.Push(GetArg(stack, args, 1)); break;

            case Code.Ldarg_2: stack.Push(GetArg(stack, args, 2)); break;

            case Code.Ldarg_3: stack.Push(GetArg(stack, args, 3)); break;

            case Code.Ldloc:
            case Code.Ldloc_S: stack.Push(GetLocal(stack, locals, (Local)instr.Operand)); break;

            case Code.Ldloc_0: stack.Push(GetLocal(stack, locals, 0)); break;

            case Code.Ldloc_1: stack.Push(GetLocal(stack, locals, 1)); break;

            case Code.Ldloc_2: stack.Push(GetLocal(stack, locals, 2)); break;

            case Code.Ldloc_3: stack.Push(GetLocal(stack, locals, 3)); break;

            case Code.Ldloca:
            case Code.Ldloca_S: Translate_Ldloca(stack, locals, (Local)instr.Operand); break;

            case Code.Dup: stack.CopyTop(); break;

            case Code.Ldc_I4: stack.Push(ctx.MkBV((int)instr.Operand, 32)); break;

            case Code.Ldc_I4_S: stack.Push(ctx.MkBV((sbyte)instr.Operand, 32)); break;

            case Code.Ldc_I4_0: stack.Push(ctx.MkBV(0, 32)); break;

            case Code.Ldc_I4_1: stack.Push(ctx.MkBV(1, 32)); break;

            case Code.Ldc_I4_2: stack.Push(ctx.MkBV(2, 32)); break;

            case Code.Ldc_I4_3: stack.Push(ctx.MkBV(3, 32)); break;

            case Code.Ldc_I4_4: stack.Push(ctx.MkBV(4, 32)); break;

            case Code.Ldc_I4_5: stack.Push(ctx.MkBV(5, 32)); break;

            case Code.Ldc_I4_6: stack.Push(ctx.MkBV(6, 32)); break;

            case Code.Ldc_I4_7: stack.Push(ctx.MkBV(7, 32)); break;

            case Code.Ldc_I4_8: stack.Push(ctx.MkBV(8, 32)); break;

            case Code.Ldc_I4_M1: stack.Push(ctx.MkBV(-1, 32)); break;

            case Code.Ldnull: stack.Push(stack.Unknown()); break;

            case Code.Ldstr: stack.Push(stack.Unknown()); break;

            case Code.Add: Translate_Add(stack, instr); break;

            case Code.Sub: Translate_Sub(stack, instr); break;

            case Code.Mul: Translate_Mul(stack, instr); break;

            case Code.Div: Translate_Div(stack, instr); break;

            case Code.Div_Un: Translate_Div_Un(stack, instr); break;

            case Code.Rem: Translate_Rem(stack, instr); break;

            case Code.Rem_Un: Translate_Rem_Un(stack, instr); break;

            case Code.Neg: Translate_Neg(stack, instr); break;

            case Code.And: Translate_And(stack, instr); break;

            case Code.Or: Translate_Or(stack, instr); break;

            case Code.Xor: Translate_Xor(stack, instr); break;

            case Code.Not: Translate_Not(stack, instr); break;

            case Code.Shl: Translate_Shl(stack, instr); break;

            case Code.Shr: Translate_Shr(stack, instr); break;

            case Code.Shr_Un: Translate_Shr_Un(stack, instr); break;

            case Code.Ceq: Translate_Ceq(stack, instr); break;

            case Code.Cgt: Translate_Cgt(stack, instr); break;

            case Code.Cgt_Un: Translate_Cgt_Un(stack, instr); break;

            case Code.Clt: Translate_Clt(stack, instr); break;

            case Code.Clt_Un: Translate_Clt_Un(stack, instr); break;

            case Code.Box: stack.Push(stack.Pop()); break;

            case Code.Unbox_Any: stack.Push(stack.Pop()); break;

            case Code.Add_Ovf: Translate_Add_Ovf(stack, instr); break;

            case Code.Add_Ovf_Un: Translate_Add_Ovf_Un(stack, instr); break;

            case Code.Sub_Ovf: Translate_Sub_Ovf(stack, instr); break;

            case Code.Sub_Ovf_Un: Translate_Sub_Ovf_Un(stack, instr); break;

            case Code.Mul_Ovf: Translate_Mul_Ovf(stack, instr); break;

            case Code.Mul_Ovf_Un: Translate_Mul_Ovf_Un(stack, instr); break;

            case Code.Ldlen: Translate_Ldlen(stack, instr); break;

            case Code.Sizeof: Translate_Sizeof(stack, instr); break;

            case Code.Ldsfld: Translate_Ldsfld(stack, instr); break;

            case Code.Ldind_I4: Translate_Ldind_I4(stack, instr); break;

            default:
                UpdateStack(stack, instr);
                break;
            }
        }