internal static bool AreEquivalent(Instruction source, Instruction target) { if (source.OpCode.Code != target.OpCode.Code) return false; if (source.OpCode.Code == Code.Ldstr) return true; //Check the types in ldarg stuff. Sometimes this scheme //could lead us to false positives. We need an analysis //which depends on the context. if (source.IsLoadArgument ()) { // case where 'ldarg this' is used (p.GetSequence () would be 0) if (!Current.HasParameters && !Target.HasParameters) return true; return AreEquivalent (source.GetParameter (Current), target.GetParameter (Target)); } // The same for ldloc / stloc if (source.IsLoadLocal () || source.IsStoreLocal ()) return AreEquivalent (source.GetVariable (Current), target.GetVariable (Target)); //WARNING: Dirty Evil Hack: this should be in the //Pattern class if (source.OpCode.Code == Code.Ret && source.Previous != null && (source.Previous.OpCode.StackBehaviourPush == StackBehaviour.Pushi || source.Previous.OpCode.Code == Code.Ldnull || source.Previous.OpCode.StackBehaviourPush == StackBehaviour.Push1)) return false; //if (source.Operand != target.Operand) if (source.Operand != null && target.Operand != null) { // we're sure that target.Operand is of the same type as source.Operand (same OpCode is used) Instruction si = (source.Operand as Instruction); if (si != null) return (si.Offset == ((Instruction) target.Operand).Offset); IMetadataTokenProvider sm = (source.Operand as IMetadataTokenProvider); if (sm != null) return sm.Equals (target.Operand as IMetadataTokenProvider); if (source.Operand == target.Operand) return true; // last chance: we do call ToString if (source.Operand.ToString () != target.Operand.ToString ()) return false; } return true; }
private static bool CheckCeqInstruction (Instruction instruction, MethodDefinition method) { bool problem = false; switch (instruction.OpCode.Code) { case Code.Conv_R_Un: case Code.Conv_R4: case Code.Conv_R8: return true; case Code.Ldc_R4: return !CheckFloatConstants ((float) instruction.Operand); case Code.Ldc_R8: return !CheckDoubleConstants ((double) instruction.Operand); case Code.Ldelem_R4: case Code.Ldelem_R8: return true; case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: case Code.Ldloc_S: case Code.Ldloc: case Code.Ldloca: case Code.Ldloca_S: return instruction.GetVariable (method).VariableType.IsFloatingPoint (); case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: case Code.Ldarg: case Code.Ldarg_S: case Code.Ldarga: case Code.Ldarga_S: ParameterDefinition parameter = instruction.GetParameter (method); // handle 'this' if (parameter == null) return method.DeclaringType.IsFloatingPoint (); return parameter.ParameterType.IsFloatingPoint (); case Code.Call: case Code.Callvirt: MethodReference call = instruction.Operand as MethodReference; return call.ReturnType.IsFloatingPoint (); case Code.Ldfld: case Code.Ldflda: case Code.Ldsfld: case Code.Ldsflda: FieldReference field = instruction.Operand as FieldReference; return field.FieldType.IsFloatingPoint (); } return problem; }
private static Instruction StoreLoadLocal (MethodDefinition method, Instruction ins) { // check for a STLOC followed by a LDLOC if (!ins.IsLoadLocal () || !ins.Previous.IsStoreLocal ()) return null; // make sure it's about the same local variable if (ins.GetVariable (method) != ins.Previous.GetVariable (method)) return null; return ins.Previous.Previous; }
private static bool AreMirrorInstructions (Instruction ld, Instruction st, MethodDefinition method) { return (ld.GetVariable (method).Index == st.GetVariable (method).Index); }
// true == handled // false == unhandled bool CheckIfStored (Instruction afterLdstr) { switch (afterLdstr.OpCode.Code) { case Code.Stfld: // store into field case Code.Stsfld: CheckIdentifier ((afterLdstr.Operand as FieldReference).Name); break; default: if (afterLdstr.IsStoreLocal ()) CheckIdentifier (afterLdstr.GetVariable (method_body.Method).Name); else return false; break; } return true; // handled }
static string CheckDoubleAssignementOnInstanceFields (MethodDefinition method, Instruction ins, Instruction next) { // for an instance fiels the pattern is more complex because we must check that we're assigning to the same instance // first we go forward: DUP, STLOC, STFLD, LDLOC, STFLD Instruction load = next.Next; if ((load == null) || !load.IsLoadLocal ()) return String.Empty; // check that this is the same variable VariableDefinition vd1 = ins.GetVariable (method); VariableDefinition vd2 = load.GetVariable (method); if (vd1.Index != vd2.Index) return String.Empty; Instruction stfld = load.Next; if ((stfld == null) || (stfld.OpCode.Code != Code.Stfld)) return String.Empty; // check that we're assigning the same field twice FieldReference fd1 = (next.Operand as FieldReference); FieldReference fd2 = (stfld.Operand as FieldReference); if (fd1.MetadataToken.RID != fd2.MetadataToken.RID) return String.Empty; // backward: DUP, (possible CONV), LD (value to be duplicated), LD instance, LD instance if (stfld.TraceBack (method).GetOperand (method) != next.TraceBack (method).GetOperand (method)) return String.Empty; return String.Format ("Instance field '{0}' on same variable '{1}'.", fd1.Name, vd1.Name); }
static string CheckDoubleAssignement (MethodDefinition method, Instruction ins, Instruction next) { // for a static field the pattern is // DUP, STSFLD, STSFLD if (ins.OpCode.Code == Code.Stsfld) { if (next.OpCode.Code != Code.Stsfld) return String.Empty; // check that we're assigning the same field twice FieldDefinition fd1 = ins.GetField (); FieldDefinition fd2 = next.GetField (); if (fd1.MetadataToken.RID != fd2.MetadataToken.RID) return String.Empty; return String.Format ("Static field '{0}'.", fd1.Name); } else if (ins.IsStoreLocal ()) { // for a local variable the pattern is // DUP, STLOC, STLOC VariableDefinition vd2 = next.GetVariable (method); // check that we're assigning the same variable twice if (vd2 != null) { VariableDefinition vd1 = ins.GetVariable (method); if (vd1.Index != vd2.Index) return String.Empty; return String.Format ("Local variable '{0}'.", vd1.Name); } else if (next.OpCode.Code == Code.Stfld) { // instance fields are a bit more complex... return CheckDoubleAssignementOnInstanceFields (method, ins, next); } } return String.Empty; }
void CheckReassignment (MethodDefinition method, Instruction ins) { VariableDefinition v = ins.GetVariable (method); ulong index = (ulong) v.Index; if (locals.Get (index)) { string msg = String.Format (CultureInfo.InvariantCulture, "Local {0}is not disposed before being re-assigned.", GetFriendlyNameOrEmpty (v)); Runner.Report (method, ins, Severity.High, Confidence.Normal, msg); } else { locals.Set (index); } }
void Clear (MethodDefinition method, Instruction ins) { VariableDefinition v = ins.GetVariable (method); if (v != null) locals.Clear ((ulong) v.Index); }
Instruction FindRelatedSuspectLocal (MethodDefinition method, Instruction ins) { ins = LocalTraceBack (method, ins); if (null == ins) return null; int index = ins.GetVariable (method).Index; foreach (var local in suspectLocals) { if (local.GetVariable (method).Index == index) return local; } return null; }