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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #8
0
 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);
 }
Пример #9
0
        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);
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
 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);
 }
Пример #12
0
        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);
        }