public void AlwaysTrueCustomLogic() { MethodSignature ms = new MethodSignature(null, (method) => (true)); Assert.IsFalse(ms.Matches(null), "null"); Assert.IsTrue(ms.Matches(GetMethod("TestMatch")), "anything"); }
public void AlwaysTrueCustomLogic_CheckReturnValue() { MethodSignature ms = new MethodSignature(null, "System.Void", (method) => (true)); Assert.IsFalse(ms.Matches(null), "null"); Assert.IsTrue(ms.Matches(GetMethod("TestMatch")), "any name returning void"); Assert.IsFalse(ms.Matches(GetMethod("Method")), "bool"); }
/// <summary> /// Returns the first MethodDefinition that satisfies a given MethodSignature. /// </summary> /// <param name="self">The TypeReference on which the extension method can be called.</param> /// <param name="signature">The MethodSignature to match.</param> /// <returns>The first MethodDefinition for wich signature.Matches returns true.</returns> /// <remarks> /// Do not allocate a MethodSignature for only one call. Use one of the other GetMethod overloads instead. /// </remarks> public static MethodDefinition GetMethod(this TypeReference self, MethodSignature signature) { if (signature == null) { throw new ArgumentNullException("signature"); } if (self == null) { return(null); } TypeDefinition type = self.Resolve(); if (type == null) { return(null); } if (type.HasMethods) { foreach (MethodDefinition method in type.Methods) { if (signature.Matches(method)) { return(method); } } } return(null); }
private void CheckCallingBaseMethod(TypeReference type, MethodSignature methodSignature) { MethodDefinition method = type.GetMethod(methodSignature); if (method == null) { return; // Perhaps should report that doesn't exist the method (only with ctor). } // is there any Call or Callvirt instructions in the method if (OpCodeBitmask.Calls.Intersect(OpCodeEngine.GetBitmask(method))) { // in this case we check further foreach (Instruction instruction in method.Body.Instructions) { if (instruction.OpCode.FlowControl != FlowControl.Call) { continue; } MethodReference operand = (MethodReference)instruction.Operand; TypeReference tr = operand.DeclaringType; if (methodSignature.Matches(operand) && type.Inherits(tr.Namespace, tr.Name)) { return; } } } Runner.Report(method, Severity.High, Confidence.High); }
public RuleResult CheckMethod(MethodDefinition method) { // if method has no IL, the rule doesn't apply if (!method.HasBody) { return(RuleResult.DoesNotApply); } // and when the IL contains a Call[virt] instruction if (!OpCodeEngine.GetBitmask(method).Intersect(OpCodeBitmask.Calls)) { return(RuleResult.DoesNotApply); } foreach (Instruction instruction in method.Body.Instructions) { if (instruction.OpCode.FlowControl != FlowControl.Call) { continue; } MethodReference mr = (instruction.Operand as MethodReference); if (formatSignature.Matches(mr) && mr.DeclaringType.IsNamed("System", "String")) { CheckCallToFormatter(instruction, method); } } return(Runner.CurrentRuleResult); }
static bool AreCastsOk(Instruction ins) { switch (ins.OpCode.Code) { case Code.Isinst: return(true); case Code.Call: case Code.Callvirt: return(GetTypeSig.Matches(ins.Operand as MethodReference)); default: return(false); } }
public RuleResult CheckMethod(MethodDefinition method) { if (!method.HasBody) { return(RuleResult.DoesNotApply); } OpCodeBitmask bitmask = OpCodeEngine.GetBitmask(method); // is there any Call or Callvirt instructions in the method ? if (!OpCodeBitmask.Calls.Intersect(bitmask)) { return(RuleResult.DoesNotApply); } // is there a Ldnull instruction in the method ? if (!bitmask.Get(Code.Ldnull)) { return(RuleResult.DoesNotApply); } foreach (Instruction ins in method.Body.Instructions) { switch (ins.OpCode.Code) { case Code.Call: case Code.Callvirt: // if we're calling bool type.Equals({anytype}) if (!Equals.Matches(ins.Operand as MethodReference)) { continue; } // and that the previous, real, instruction is loading a null value // note: check the first parameter (not the instance) Instruction source = ins.TraceBack(method, -1); if ((source != null) && (source.OpCode.Code == Code.Ldnull)) { Runner.Report(method, ins, Severity.Low, Confidence.High); } break; } } return(Runner.CurrentRuleResult); }
static bool IsSignatureDictatedByInterface(IMemberDefinition method, MethodSignature sig) { foreach (InterfaceImplementation intf_ref in method.DeclaringType.Interfaces) { TypeDefinition intr = intf_ref.InterfaceType.Resolve(); if (intr == null) { continue; } foreach (MethodDefinition md in intr.Methods) { if (sig.Matches(md)) { return(true); } } } return(false); }
private void CheckIfAllFieldsAreDisposed(MethodDefinition method, ICollection <FieldDefinition> fields) { if (method.HasBody) { OpCodeBitmask bitmask = OpCodeEngine.GetBitmask(method); if (OpCodeBitmask.Calls.Intersect(bitmask)) { //Check if Dispose(bool) is called and if all fields are disposed foreach (Instruction ins in method.Body.Instructions) { switch (ins.OpCode.Code) { case Code.Call: case Code.Callvirt: MethodDefinition md = (ins.Operand as MethodDefinition); if ((md != null) && DisposeBool.Matches(md)) { ProcessMethod(md, fields); } break; } } // besides the call[virt] if must have a Ldarg0 and Ldfld if (bitmask.Get(Code.Ldarg_0) && bitmask.Get(Code.Ldfld)) { ProcessMethod(method, fields); } } } if (fields.Count == 0) { return; } foreach (FieldDefinition field in fields) { string s = String.Format(CultureInfo.InvariantCulture, "Since {0} is Disposable {1}() should call {0}.Dispose()", field.Name, method.Name); Runner.Report(field, Severity.High, Confidence.High, s); } }
static bool IsSignatureDictatedByOverride(IMemberDefinition method, MethodSignature sig) { TypeDefinition baseType = method.DeclaringType.BaseType.Resolve(); while (baseType != null) { if (baseType.HasMethods) { foreach (MethodDefinition md in baseType.Methods) { if (!md.IsConstructor && sig.Matches(md)) { return(true); } } } TypeReference tr = baseType.BaseType; baseType = tr == null ? null : tr.Resolve(); } return(false); }
private string PreflightVirtualMethod(MethodDefinition method) { if (MethodSignatures.ToString.Matches(method)) { return("Object.ToString"); // these names should match those used within the rule description } else if (MethodSignatures.Equals.Matches(method)) { is_equals = true; return("Object.Equals"); } else if (MethodSignatures.GetHashCode.Matches(method)) { return("Object.GetHashCode"); } else if (MethodSignatures.Finalize.Matches(method)) { return("Finalizers"); } else if (MethodSignatures.Dispose.Matches(method) || MethodSignatures.DisposeExplicit.Matches(method)) { if (method.DeclaringType.Implements("System", "IDisposable")) { return("IDisposable.Dispose"); } } else if (equals_signature != null && equals_signature.Matches(method)) { return("IEqualityComparer<T>.Equals"); } else if (hashcode_signature != null && hashcode_signature.Matches(method)) { allowedExceptions = HashCodeExceptions; return("IEqualityComparer<T>.GetHashCode"); } return(String.Empty); }
public RuleResult CheckMethod(MethodDefinition method) { if (!Dispose.Matches(method)) { return(RuleResult.DoesNotApply); } if (!method.HasBody || !method.HasThis) { return(RuleResult.DoesNotApply); } // rule only applies to type that implements IDisposable if (!method.DeclaringType.Implements("System", "IDisposable")) { return(RuleResult.DoesNotApply); } // avoid looping if we're sure there's no call in the method if (!OpCodeBitmask.Calls.Intersect(OpCodeEngine.GetBitmask(method))) { Runner.Report(method, Severity.Medium, Confidence.High); return(RuleResult.Failure); } // it's ok if the code is not compiled for DEBUG or TRACE purposes if (method.HasCustomAttributes) { if (!HasConditionalAttributeForDebugging(method.CustomAttributes)) { return(RuleResult.Success); } } var parentType = method.DeclaringType.BaseType; if (parentType.Implements("System", "IDisposable") && !parentType.FullName.StartsWith("System.Windows.Forms")) { return(RuleResult.DoesNotApply); } foreach (Instruction ins in method.Body.Instructions) { // look for a call... if (ins.OpCode.FlowControl != FlowControl.Call) { continue; } // ... to System.Diagnostics.Debug ... MethodReference mr = (ins.Operand as MethodReference); if (mr.DeclaringType.FullName != Debug) { continue; } // ... WriteLineIf methods if (mr.Name == "WriteLineIf") { var parameters = mr.Parameters; for (int i = 0; i < parameters.Count; i++) { if (parameters[i].ParameterType.FullName == "System.String") { var output = GetLoadStringInstruction(ins, method, i); if (string.IsNullOrEmpty(output) || !output.ToLower().Contains("missing dispose")) { Runner.Report(method, ins, Severity.Medium, Confidence.Normal); } return(Runner.CurrentRuleResult); } } } } // Didn't find a WriteLineIf Runner.Report(method, Severity.Medium, Confidence.High); return(RuleResult.Failure); }