Пример #1
0
        // small patterns that highly suggest they were compiler generated
        bool ComputeUnlikelyUserPatterns()
        {
            bool call = false;

            for (int i = 0; i < Count; i++)
            {
                Instruction ins = instructions [i];
                // foreach
                if (ins.OpCode.Code == Code.Callvirt)
                {
                    MethodReference mr = (ins.Operand as MethodReference);
                    if (mr.IsNamed("System.Collections", "IEnumerator", "get_Current"))
                    {
                        return(true);
                    }
                    if (mr.IsNamed("System.Collections", "IEnumerator", "MoveNext"))
                    {
                        return(!call);
                    }
                }
                // if there's a unknown call then it's likely not (totally) compiler generated
                call |= (ins.OpCode.FlowControl == FlowControl.Call);
                // foreach
                if (IsInstanceOfIDisposable(ins))
                {
                    return(true);
                }
                // foreach, using
                if (IsIDisposableDisposePattern(ins))
                {
                    return(true);
                }
            }
            return(false);
        }
Пример #2
0
        public RuleResult CheckMethod(MethodDefinition method)
        {
            // rule doesn't apply if the method has no IL
            if (!method.HasBody)
            {
                return(RuleResult.DoesNotApply);
            }

            // avoid looping if we're sure there's no call in the method
            if (!OpCodeBitmask.Calls.Intersect(OpCodeEngine.GetBitmask(method)))
            {
                return(RuleResult.DoesNotApply);
            }

            int enter = 0;
            int exit  = 0;

            foreach (Instruction ins in method.Body.Instructions)
            {
                if (ins.OpCode.FlowControl != FlowControl.Call)
                {
                    continue;
                }

                MethodReference m = (ins.Operand as MethodReference);
                if (m == null)
                {
                    continue;
                }

                if (m.IsNamed("System.Threading", "Monitor", "Enter"))
                {
                    enter++;
                }
                else if (m.IsNamed("System.Threading", "Monitor", "Exit"))
                {
                    exit++;
                }
            }

            if (enter == exit)
            {
                return(RuleResult.Success);
            }

            Runner.Report(method, Severity.High, Confidence.Normal);
            return(RuleResult.Failure);
        }
        private static bool IsGetNow(Instruction ins)
        {
            if (ins.OpCode.Code != Code.Call)
            {
                return(false);
            }

            MethodReference calledMethod = (MethodReference)ins.Operand;

            return(calledMethod.IsNamed("System", "DateTime", "get_Now"));
        }
        public RuleResult CheckMethod(MethodDefinition method)
        {
            if (!method.HasBody)
            {
                return(RuleResult.DoesNotApply);
            }

            // is there any Newobj instructions in this method
            if (!OpCodeEngine.GetBitmask(method).Get(Code.Newobj))
            {
                return(RuleResult.DoesNotApply);
            }

            StackEntryAnalysis sea = null;

            foreach (Instruction ins in method.Body.Instructions)
            {
                if (ins.OpCode.Code != Code.Newobj)
                {
                    continue;
                }

                MethodReference constructor = (MethodReference)ins.Operand;

                if (!constructor.DeclaringType.IsNamed("System.Threading", "Thread"))
                {
                    continue;
                }
                if (ins.Next != null && (ins.Next.OpCode.Code == Code.Call || ins.Next.OpCode.Code == Code.Callvirt))                   //quick check to safe resources
                {
                    MethodReference calledMethod = (MethodReference)ins.Next.Operand;
                    if (calledMethod.IsNamed("System.Threading", "Thread", "Start"))
                    {
                        continue;
                    }
                }

                if (sea == null)
                {
                    sea = new StackEntryAnalysis(method);
                }

                StackEntryUsageResult [] usageResults = sea.GetStackEntryUsage(ins);

                if (!CheckUsage(usageResults))
                {
                    // Critical because code cannot work as intented
                    Runner.Report(method, ins, Severity.Critical, Confidence.High, String.Empty);
                }
            }

            return(Runner.CurrentRuleResult);
        }
        public RuleResult CheckMethod(MethodDefinition method)
        {
            // rule apply only if the method has a body (e.g. p/invokes, icalls don't)
            if (!method.HasBody)
            {
                return(RuleResult.DoesNotApply);
            }

            // is there any Call or Callvirt instructions in the method ?
            if (!OpCodeBitmask.Calls.Intersect(OpCodeEngine.GetBitmask(method)))
            {
                return(RuleResult.DoesNotApply);
            }

            foreach (Instruction ins in method.Body.Instructions)
            {
                if ((ins.OpCode.Code != Code.Call) && (ins.OpCode.Code != Code.Callvirt))
                {
                    continue;
                }

                // look for String.Concat overloads using System.Object
                MethodReference mr = (ins.Operand as MethodReference);
                if (!mr.HasParameters || !mr.IsNamed("System", "String", "Concat"))
                {
                    continue;
                }

                TypeReference ptype = mr.Parameters [0].ParameterType;
                if (ptype.Namespace != "System")
                {
                    continue;                     // very unlikely
                }
                switch (ptype.Name)
                {
                case "Object":
                    CheckParameters(mr, method, ins);
                    break;

                case "Object[]":
                    if ((ins.Previous.OpCode.Code == Code.Stelem_Ref) || ins.Previous.IsLoadLocal())
                    {
                        ScanArray(method, ins.Previous);
                    }
                    break;
                }
            }

            return(Runner.CurrentRuleResult);
        }
Пример #6
0
        public RuleResult CheckMethod(MethodDefinition method)
        {
            // rule doesn't not apply to methods without code (e.g. p/invokes)
            if (!method.HasBody)
            {
                return(RuleResult.DoesNotApply);
            }

            // is there any Call or Callvirt instructions in the method
            OpCodeBitmask calls = OpCodeBitmask.Calls;

            if (!calls.Intersect(OpCodeEngine.GetBitmask(method)))
            {
                return(RuleResult.DoesNotApply);
            }

            // go!

            // we look for a call to String.Length property (since it's much easier
            // than checking a string being compared to null)
            foreach (Instruction current in method.Body.Instructions)
            {
                if (!calls.Get(current.OpCode.Code))
                {
                    continue;
                }

                MethodReference mr = (current.Operand as MethodReference);
                if (mr.IsNamed("System", "String", "get_Length"))
                {
                    // now that we found it we check that
                    // 1 - we previously did a check null on the same value (that we already know is a string)
                    Instruction branch = PreLengthCheck(method, current.Previous);
                    if (branch == null)
                    {
                        continue;
                    }
                    // 2 - we compare the return value (length) with 0
                    if (PostLengthCheck(current.Next, branch))
                    {
                        Runner.Report(method, current, Severity.Medium, Confidence.High);
                    }
                }
            }
            return(Runner.CurrentRuleResult);
        }
        protected override bool IsSpecialCase(MethodReference method)
        {
            if ((method == null) || method.IsNamed("System", "Activator", "CreateInstance"))
            {
                return(true);
            }

            TypeReference type = method.DeclaringType;

            if (!type.IsNamed("System.Resources", "ResourceManager"))
            {
                return(false);
            }

            string name = method.Name;

            return(name == "GetObject" || name == "GetString");
        }
Пример #8
0
        static bool IsMonitorEnter(Instruction ins, int parametersCount)
        {
            // VS2008 like to includes a few NOP
            while (ins != null && ins.OpCode.Code == Code.Nop)
            {
                ins = ins.Previous;
            }
            if (ins == null)
            {
                return(false);
            }

            MethodReference method = (ins.Operand as MethodReference);

            if (!method.IsNamed("System.Threading", "Monitor", "Enter"))
            {
                return(false);
            }
            return(parametersCount == method.Parameters.Count);
        }
        private bool Recurse(MethodDefinition method, int level)
        {
            // some methods have no body (e.g. p/invokes, icalls)
            if ((method == null) || !method.HasBody)
            {
                return(false);
            }

            // don't iterate the IL unless we know there are some call[virt] inside them
            if (!OpCodeBitmask.Calls.Intersect(OpCodeEngine.GetBitmask(method)))
            {
                return(false);
            }

            foreach (Instruction ins in method.Body.Instructions)
            {
                switch (ins.OpCode.Code)
                {
                case Code.Call:
                case Code.Callvirt:
                    // are we calling GC.SuppressFinalize ?
                    MethodReference callee = (ins.Operand as MethodReference);
                    if (callee.IsNamed("System", "GC", "SuppressFinalize"))
                    {
                        return(true);
                    }
                    else if (level < 3)
                    {
                        if (Recurse(callee.Resolve(), level + 1))
                        {
                            return(true);
                        }
                    }
                    break;
                }
            }
            return(false);
        }
        public RuleResult CheckMethod(MethodDefinition method)
        {
            if (!method.HasBody)
            {
                return(RuleResult.DoesNotApply);
            }

            // avoid looping if we're sure there's no call in the method
            if (!OpCodeBitmask.Calls.Intersect(OpCodeEngine.GetBitmask(method)))
            {
                return(RuleResult.DoesNotApply);
            }

            foreach (Instruction ins in method.Body.Instructions)
            {
                MethodReference mr = ins.GetMethod();
                if (mr.IsNamed("System.Threading", "Monitor", "Enter"))
                {
                    Analyze(method, mr, ins);
                }
            }
            return(Runner.CurrentRuleResult);
        }
Пример #11
0
        // the rule idea came from
        // http://lists.ximian.com/archives/public/mono-patches/2008-June/121564.html

        public RuleResult CheckMethod(MethodDefinition method)
        {
            // rule apply only if the method has a body (e.g. p/invokes, icalls don't)
            if (!method.HasBody)
            {
                return(RuleResult.DoesNotApply);
            }

            // is there any Call or Callvirt instructions in the method ?
            OpCodeBitmask bitmask = OpCodeEngine.GetBitmask(method);

            if (!OpCodeBitmask.Calls.Intersect(bitmask))
            {
                return(RuleResult.DoesNotApply);
            }
            // and a call to Ldstr ?
            if (!bitmask.Get(Code.Ldstr))
            {
                return(RuleResult.DoesNotApply);
            }

            foreach (Instruction ins in method.Body.Instructions)
            {
                if (ins.OpCode.FlowControl != FlowControl.Call)
                {
                    continue;
                }

                // look for calls to: static Type System.Type.GetType(string...)
                MethodReference mr = (ins.Operand as MethodReference);
                if ((mr == null) || !mr.HasParameters)
                {
                    continue;
                }
                if (!mr.IsNamed("System", "Type", "GetType"))
                {
                    continue;
                }

                if (ins.Previous.OpCode.Code != Code.Ldstr)
                {
                    continue;
                }

                string type_name = (ins.Previous.Operand as string);
                // one good reason to use this (besides non-visible types) is get a type from an unreferenced assembly
                if ((type_name == null) || type_name.Contains(", "))
                {
                    continue;
                }
                // another good reason is the supported way to detect if running on mono runtime
                if (type_name == "Mono.Runtime")
                {
                    continue;
                }

                string msg = String.Format(CultureInfo.InvariantCulture,
                                           "Replace call to Type.GetType(\"{0}\") into typeof({0}).", type_name);
                Runner.Report(method, ins, Severity.Medium, Confidence.Normal, msg);
            }
            return(Runner.CurrentRuleResult);
        }