Example #1
0
        private static bool IsBaseFinalizeCalled(MethodDefinition finalizer)
        {
            if (!OpCodeBitmask.Calls.Intersect(OpCodeEngine.GetBitmask(finalizer)))
            {
                return(false);
            }

            foreach (Instruction current in finalizer.Body.Instructions)
            {
                switch (current.OpCode.Code)
                {
                case Code.Call:
                case Code.Callvirt:
                    MethodReference mr = (current.Operand as MethodReference);
                    if ((mr != null) && mr.IsFinalizer())
                    {
                        return(true);
                    }
                    break;
                }
            }
            return(false);
        }
Example #2
0
        public RuleResult CheckType(TypeDefinition type)
        {
            // rule applies only to type with a finalizer
            MethodDefinition finalizer = type.GetMethod(MethodSignatures.Finalize);

            if (finalizer == null)
            {
                return(RuleResult.DoesNotApply);
            }

            // rule applies

            // finalizer is present, look if it has any code within it
            // i.e. look if is does anything else than calling it's base class
            int nullify_fields = 0;

            foreach (Instruction ins in finalizer.Body.Instructions)
            {
                switch (ins.OpCode.Code)
                {
                case Code.Call:
                case Code.Callvirt:
                    // it's empty if we're calling the base class finalizer
                    MethodReference mr = (ins.Operand as MethodReference);
                    if ((mr == null) || !mr.IsFinalizer())
                    {
                        return(RuleResult.Success);
                    }
                    break;

                case Code.Nop:
                case Code.Leave:
                case Code.Leave_S:
                case Code.Ldarg_0:
                case Code.Endfinally:
                case Code.Ret:
                case Code.Ldnull:
                    // ignore
                    break;

                case Code.Stfld:
                    // considered as empty as long as it's only to nullify them
                    if (ins.Previous.OpCode.Code == Code.Ldnull)
                    {
                        nullify_fields++;
                        continue;
                    }
                    return(RuleResult.Success);

                default:
                    // finalizer isn't empty (normal)
                    return(RuleResult.Success);
                }
            }

            // finalizer is empty (bad / useless)
            string msg = nullify_fields == 0 ? String.Empty :
                         String.Format(CultureInfo.InvariantCulture,
                                       "Contains {0} fields being nullified needlessly", nullify_fields);

            Runner.Report(type, Severity.Medium, Confidence.Normal, msg);
            return(RuleResult.Failure);
        }