public void VisitBinary(BinaryOp op) { if (m_offset < 0 && (op.Untyped.OpCode.Code == Code.Div || op.Untyped.OpCode.Code == Code.Div_Un)) { do { LoadConstantInt load1 = m_info.Instructions[op.Index - 1] as LoadConstantInt; if (load1 != null) { if (load1.Value == 0) { m_offset = op.Untyped.Offset; Log.DebugLine(this, "zero constant denominator at {0:X2}", m_offset); } break; } LoadLocal load2 = m_info.Instructions[op.Index - 1] as LoadLocal; if (load2 != null) { if (DoIsIntType(load2.Type)) { State state = m_info.Tracker.State(op.Index - 1); long? value = state.Locals[load2.Variable]; if (value.HasValue && value.Value == 0) { m_offset = op.Untyped.Offset; Log.DebugLine(this, "zero local denominator at {0:X2}", m_offset); } } break; } LoadArg load3 = m_info.Instructions[op.Index - 1] as LoadArg; if (load3 != null) { if (DoIsIntType(load3.Type)) { State state2 = m_info.Tracker.State(op.Index - 1); long? value2 = state2.Arguments[m_info.Method.HasThis ? load3.Arg : load3.Arg - 1]; if (value2.HasValue && value2.Value == 0) { m_offset = op.Untyped.Offset; Log.DebugLine(this, "zero arg denominator at {0:X2}", m_offset); } } break; } }while (false); } }
private void DoCheck(MethodInfo info) { if (info.Instructions.Length == 2) { LoadConstantInt load = info.Instructions[0] as LoadConstantInt; End end = info.Instructions[1] as End; if (load != null && end != null && end.Untyped.OpCode.Code == Code.Ret) { Log.DebugLine(this, "returns constant"); Reporter.MethodFailed(info.Method, CheckID, 0, string.Empty); } } }
public void VisitNew(NewArr newer) { if (newer.Type.FullName == "System.Type") { Log.DebugLine(this, " new {0}[] at {1:X2}", newer.Type.FullName, newer.Untyped.Offset); LoadConstantInt load = m_info.Instructions[newer.Index - 1] as LoadConstantInt; if (load != null) { if (load.Value == 0) { Reporter.MethodFailed(m_info.Method, CheckID, newer.Untyped.Offset, string.Empty); } } } }
public void VisitStore(StoreLocal store) { if (store.Index > 0) { LoadConstantInt load = m_info.Instructions[store.Index - 1] as LoadConstantInt; if (load != null) { if (load.Value < 0 || load.Value > 255) { Log.DebugLine(this, "store at {0:X2}", store.Untyped.Offset); if (m_stores.IndexOf(store.Variable) < 0) { m_stores.Add(store.Variable); } } } } }
public void VisitCompare(Compare op) { // Compiler sometimes generates this code to return true. if (op.Index >= 2) { // ldc.i4.0 // ldc.i4.0 // ceq LoadConstantInt rhs = m_info.Instructions[op.Index - 1] as LoadConstantInt; LoadConstantInt lhs = m_info.Instructions[op.Index - 2] as LoadConstantInt; if (lhs != null && rhs != null && lhs.Value == 0 && rhs.Value == 0) { return; } } if (m_offset < 0) { DoCheck(op); } }
// This method is used by the Transform above and later on when we // need to compute the state for each instruction in a method. public Lattice Transform(int index) { DBC.Pre(index >= 0 && index < m_instructions.Length, "index is oor"); // real code would probably use FastPre StoreLocal store = m_instructions[index] as StoreLocal; if (store != null) { LoadConstantInt load = m_instructions[index - 1] as LoadConstantInt; // test code so we only track constant loads if (load != null) { return(new Lattice(m_instructions, new State(load.Value))); } else { return(new Lattice(m_instructions, Indeterminate)); } } return(this); }
private void DoCheckLoad(TypedInstruction instruction) { LoadConstantInt load = m_info.Instructions[instruction.Index - 1] as LoadConstantInt; if (load != null) { if (load.Value < 0 || load.Value > 255) { m_offset = instruction.Untyped.Offset; Log.DebugLine(this, "bad exit at {0:X2}", m_offset); } } LoadLocal local = m_info.Instructions[instruction.Index - 1] as LoadLocal; if (local != null) { Log.DebugLine(this, "{0} at {1:X2}", instruction.Untyped.OpCode, instruction.Untyped.Offset); if (m_candidateLoads.IndexOf(local.Variable) < 0) { m_candidateLoads.Add(local.Variable); } } }
public static bool IsIntOperand(MethodInfo info, int index, int nth) { bool isInt = false; int i = info.Tracker.GetStackIndex(index, nth); if (i >= 0) { do { LoadArg arg = info.Instructions[i] as LoadArg; if (arg != null && arg.Arg >= 1) { ParameterDefinition p = info.Method.Parameters[arg.Arg - 1]; if (p.ParameterType.FullName == "System.Int32") { isInt = true; } break; } LoadConstantInt constant = info.Instructions[i] as LoadConstantInt; if (constant != null) { Code code = constant.Untyped.OpCode.Code; switch (code) { case Code.Ldc_I4_M1: case Code.Ldc_I4_0: case Code.Ldc_I4_1: case Code.Ldc_I4_2: case Code.Ldc_I4_3: case Code.Ldc_I4_4: case Code.Ldc_I4_5: case Code.Ldc_I4_6: case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_S: case Code.Ldc_I4: isInt = true; break; } break; } LoadField field = info.Instructions[i] as LoadField; if (field != null) { if (field.Field.FieldType.FullName == "System.Int32") { isInt = true; } break; } LoadLocal local = info.Instructions[i] as LoadLocal; if (local != null) { VariableDefinition v = info.Method.Body.Variables[local.Variable]; if (v.VariableType.FullName == "System.Int32") { isInt = true; } break; } LoadStaticField sfield = info.Instructions[i] as LoadStaticField; if (sfield != null) { if (sfield.Field.FieldType.FullName == "System.Int32") { isInt = true; } break; } }while (false); } return(isInt); }
private void DoStackPushes(List <StackEntry> stack, int index, List <StackEntry> oldStack) { long?value; TypedInstruction instruction = m_instructions[index]; switch (instruction.Untyped.OpCode.Code) { case Code.Add: case Code.Sub: case Code.Mul: case Code.Div: case Code.Div_Un: case Code.Rem: case Code.Rem_Un: case Code.And: case Code.Or: case Code.Xor: case Code.Shl: case Code.Shr: case Code.Shr_Un: case Code.Neg: case Code.Not: case Code.Add_Ovf: case Code.Add_Ovf_Un: case Code.Mul_Ovf: case Code.Mul_Ovf_Un: case Code.Sub_Ovf: case Code.Sub_Ovf_Un: stack.Add(new StackEntry(null, index)); // could compute these, but we don't care too much about integer values atm break; case Code.Arglist: // push non-null case Code.Box: case Code.Ldarga: case Code.Ldarga_S: case Code.Ldelema: case Code.Ldflda: case Code.Ldftn: case Code.Ldind_Ref: case Code.Ldloca: case Code.Ldloca_S: case Code.Ldobj: case Code.Ldsflda: case Code.Ldstr: case Code.Ldtoken: case Code.Ldvirtftn: case Code.Localloc: case Code.Mkrefany: case Code.Newarr: case Code.Newobj: case Code.Refanytype: case Code.Refanyval: case Code.Unbox: case Code.Unbox_Any: stack.Add(new StackEntry(1, index)); break; case Code.Call: case Code.Calli: case Code.Callvirt: Call call = instruction as Call; if (call.Target.ReturnType.ReturnType.ToString() != "System.Void") { stack.Add(new StackEntry(null, index)); } break; case Code.Castclass: value = oldStack.Back().Value; if (value.HasValue && value.Value == 0) { stack.Add(new StackEntry(0, index)); } else { stack.Add(new StackEntry(1, index)); } break; case Code.Ceq: // push indeterminate case Code.Cgt: case Code.Cgt_Un: case Code.Clt: case Code.Clt_Un: case Code.Ckfinite: case Code.Conv_I1: case Code.Conv_I2: case Code.Conv_I4: case Code.Conv_I8: case Code.Conv_U4: case Code.Conv_U8: case Code.Conv_R4: case Code.Conv_R8: case Code.Conv_U2: case Code.Conv_U1: case Code.Conv_I: case Code.Conv_R_Un: case Code.Conv_U: case Code.Ldelem_I1: case Code.Ldelem_U1: case Code.Ldelem_I2: case Code.Ldelem_U2: case Code.Ldelem_I4: case Code.Ldelem_U4: case Code.Ldelem_I8: case Code.Ldelem_I: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Ref: case Code.Ldelem_Any: case Code.Ldind_I1: case Code.Ldind_U1: case Code.Ldind_I2: case Code.Ldind_U2: case Code.Ldind_I4: case Code.Ldind_U4: case Code.Ldind_I8: case Code.Ldind_I: case Code.Ldind_R4: case Code.Ldind_R8: case Code.Ldfld: case Code.Ldsfld: case Code.Ldlen: case Code.Sizeof: stack.Add(new StackEntry(null, index)); break; case Code.Conv_Ovf_I1: // push previous value case Code.Conv_Ovf_U1: case Code.Conv_Ovf_I2: case Code.Conv_Ovf_U2: case Code.Conv_Ovf_I4: case Code.Conv_Ovf_U4: case Code.Conv_Ovf_I8: case Code.Conv_Ovf_U8: case Code.Conv_Ovf_I: case Code.Conv_Ovf_U: case Code.Conv_Ovf_I1_Un: case Code.Conv_Ovf_I2_Un: case Code.Conv_Ovf_I4_Un: case Code.Conv_Ovf_I8_Un: case Code.Conv_Ovf_U1_Un: case Code.Conv_Ovf_U2_Un: case Code.Conv_Ovf_U4_Un: case Code.Conv_Ovf_U8_Un: case Code.Conv_Ovf_I_Un: case Code.Conv_Ovf_U_Un: value = oldStack.Back().Value; stack.Add(new StackEntry(value, index)); break; case Code.Dup: value = oldStack.Back().Value; stack.Add(new StackEntry(value, index)); stack.Add(new StackEntry(value, index)); break; case Code.Isinst: value = oldStack.Back().Value; if (value.HasValue && value.Value == 0) { stack.Add(new StackEntry(0, index)); } else { stack.Add(new StackEntry(null, index)); } break; case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: case Code.Ldarg: case Code.Ldarg_S: LoadArg arg = instruction as LoadArg; value = m_state.Arguments[arg.Arg]; stack.Add(new StackEntry(value, index)); break; case Code.Ldc_I4_M1: case Code.Ldc_I4_0: case Code.Ldc_I4_1: case Code.Ldc_I4_2: case Code.Ldc_I4_3: case Code.Ldc_I4_4: case Code.Ldc_I4_5: case Code.Ldc_I4_6: case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_S: case Code.Ldc_I4: case Code.Ldc_I8: LoadConstantInt constant = instruction as LoadConstantInt; stack.Add(new StackEntry(constant.Value, index)); break; case Code.Ldc_R4: case Code.Ldc_R8: LoadConstantFloat constant2 = instruction as LoadConstantFloat; if (constant2.Value == 0.0) { stack.Add(new StackEntry(0, index)); } else { stack.Add(new StackEntry(null, index)); } break; case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: case Code.Ldloc: case Code.Ldloc_S: LoadLocal local = instruction as LoadLocal; value = m_state.Locals[local.Variable]; stack.Add(new StackEntry(value, index)); break; case Code.Ldnull: // push null stack.Add(new StackEntry(0, index)); break; default: DBC.Assert(instruction.Untyped.OpCode.StackBehaviourPush == StackBehaviour.Push0, "Expected {0} to push nothing", instruction.Untyped.OpCode); break; } }