public RuleResult CheckType (TypeDefinition type) { // that will cover interfaces, delegates too if (!type.HasFields) return RuleResult.DoesNotApply; // rule doesn't apply to enums, interfaces, structs, delegates or generated code if (type.IsEnum || type.IsValueType || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition explicitDisposeMethod = null; MethodDefinition implicitDisposeMethod = null; bool abstractWarning = false; if (type.Implements ("System", "IDisposable")) { implicitDisposeMethod = type.GetMethod (MethodSignatures.Dispose); explicitDisposeMethod = type.GetMethod (MethodSignatures.DisposeExplicit); if (IsAbstract (implicitDisposeMethod) || IsAbstract (explicitDisposeMethod)) { abstractWarning = true; } else { return RuleResult.Success; } } FieldCandidates.Clear (); foreach (FieldDefinition field in type.Fields) { // we can't dispose static fields in IDisposable if (field.IsStatic) continue; TypeDefinition fieldType = field.FieldType.GetElementType ().Resolve (); if (fieldType == null) continue; if (FieldTypeIsCandidate (fieldType)) FieldCandidates.Add (field); } // if there are fields types that implements IDisposable if (type.HasMethods && (FieldCandidates.Count > 0)) { // check if we're assigning new object to them foreach (MethodDefinition method in type.Methods) { CheckMethod (method, abstractWarning); } } // Warn about possible confusion if the Dispose methods are abstract if (IsAbstract (implicitDisposeMethod)) Runner.Report (implicitDisposeMethod, Severity.Medium, Confidence.High, AbstractDisposeMessage); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule only apply to (non generated) delegates if (!type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition invoke = type.GetMethod ("Invoke"); // this happens for System.MulticastDelegate if (invoke == null) return RuleResult.DoesNotApply; if (!invoke.ReturnType.IsNamed ("System", "Void")) return RuleResult.Success; if (!invoke.HasParameters) return RuleResult.Success; IList<ParameterDefinition> pdc = invoke.Parameters; if (pdc.Count != 2) return RuleResult.Success; if (!pdc [0].ParameterType.IsNamed ("System", "Object")) return RuleResult.Success; if (!pdc [1].ParameterType.Inherits ("System", "EventArgs")) return RuleResult.Success; Runner.Report (type, Severity.Medium, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rules applies to types that overrides System.Object.Equals(object) MethodDefinition method = type.GetMethod (MethodSignatures.ToString); if ((method == null) || !method.HasBody) return RuleResult.DoesNotApply; // call base class to detect if the method can return null return CheckMethod (method); }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; MethodDefinition equality = type.GetMethod (MethodSignatures.op_Equality); if ((equality == null) || type.HasMethod (MethodSignatures.Equals)) return RuleResult.Success; Runner.Report (equality, Severity.High, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // handle System.Object (which can't call base class) if (type.BaseType == null) return RuleResult.DoesNotApply; MethodDefinition finalizer = type.GetMethod (MethodSignatures.Finalize); if (finalizer == null) // no finalizer found return RuleResult.DoesNotApply; if (IsBaseFinalizeCalled (finalizer)) return RuleResult.Success; Runner.Report (finalizer, Severity.Critical, Confidence.Total); return RuleResult.Failure; }
private void CheckCallingBaseMethod (TypeDefinition type, MethodSignature methodSignature) { MethodDefinition method = type.GetMethod (methodSignature); if (method == null) return; // Perhaps should report that doesn't exist the method (only with ctor). foreach (Instruction instruction in method.Body.Instructions) { if (instruction.OpCode.FlowControl == FlowControl.Call) { MethodReference operand = (MethodReference) instruction.Operand; if (methodSignature.Matches (operand) && type.Inherits (operand.DeclaringType.ToString ())) return; } } Runner.Report (method, Severity.High, Confidence.High, String.Format ("The method {0} isn't calling its base method.", method)); }
public RuleResult CheckType (TypeDefinition type) { // rules applies to types that overrides System.Object.Equals(object) MethodDefinition method = type.GetMethod (MethodSignatures.Equals); if ((method == null) || !method.HasBody || method.IsStatic) return RuleResult.DoesNotApply; // rule applies // scan IL to see if null is checked and false returned if (CheckSequence (method.Body.Instructions [0], type)) return RuleResult.Success; Runner.Report (method, Severity.Medium, Confidence.High); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule only apply to (non generated) delegates if (!type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition invoke = type.GetMethod ("Invoke"); // this happens for System.MulticastDelegate if (invoke == null) return RuleResult.DoesNotApply; int n = 0; Severity severity = Severity.Medium; bool use_structure = false; // check parameters for 'ref', 'out', 'params' if (invoke.HasParameters) { IList<ParameterDefinition> pdc = invoke.Parameters; n = pdc.Count; // too many parameters to directly use Action/Func // so we lower severity and suggest grouping them if (n > ((type.Module.Runtime >= TargetRuntime.Net_4_0) ? 16 : 4)) { severity = Severity.Low; n = 1; use_structure = true; } // special cases not directly usable with Action/Func foreach (ParameterDefinition pd in pdc) { if (pd.IsOut || pd.ParameterType.IsByReference || pd.IsParams ()) return RuleResult.Success; } } string msg = invoke.ReturnType.IsNamed ("System", "Void") ? ActionMessage [n] : FuncMessage [n]; if (use_structure) msg += " and use a structure to hold all your parameters into <T>."; Runner.Report (type, severity, Confidence.High, msg); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (!type.IsSerializable || !type.Implements ("System.Runtime.Serialization.ISerializable")) return RuleResult.DoesNotApply; MethodDefinition getObjectData = type.GetMethod (MethodSignatures.GetObjectData); if (getObjectData != null) { CheckUnusedFieldsIn (type, getObjectData); CheckExtensibilityFor (type, getObjectData); } return Runner.CurrentRuleResult; }
private MethodDefinition CacheTypeGetStoreMethod(TypeDefinition cacheInterface, string cacheTypeStoreMethodName) { return cacheInterface.GetMethod(cacheTypeStoreMethodName, cacheInterface.Module.ImportType(typeof(void)), new[] { cacheInterface.Module.ImportType<string>(), cacheInterface.Module.ImportType<object>() }); }
private MethodDefinition CacheTypeGetRetrieveMethod(TypeDefinition cacheType, string cacheTypeRetrieveMethodName) { return cacheType.GetMethod(cacheTypeRetrieveMethodName, new GenericParameter("T", cacheType), new[] { cacheType.Module.ImportType<string>() }); }
private MethodDefinition CacheTypeGetRemoveMethod(TypeDefinition cacheType, string cacheTypeRemoveMethodName) { return cacheType.GetMethod(cacheTypeRemoveMethodName, ModuleDefinition.TypeSystem.Void, new[] { cacheType.Module.ImportType<string>() }); }
public RuleResult CheckType (TypeDefinition type) { if (!type.HasFields || type.IsEnum) return RuleResult.DoesNotApply; Log.WriteLine (this); Log.WriteLine (this, "----------------------------------"); Log.WriteLine (this, type.FullName); FieldDefinition field = FindIntPtr (type); if (field != null) { Confidence confidence = Confidence.Low; MethodDefinition finalizer = type.GetMethod (MethodSignatures.Finalize); if (finalizer != null) confidence = (Confidence) ((int) confidence - 1); // lower numbers have higher confidence if (type.Implements ("System.IDisposable")) confidence = (Confidence) ((int) confidence - 1); Log.WriteLine (this, "'{0}' is an IntPtr.", field.Name); Runner.Report (field, Severity.Medium, confidence); } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { if (!type.IsSerializable || !type.Implements ("System.Runtime.Serialization", "ISerializable")) return RuleResult.DoesNotApply; MethodDefinition getObjectData = type.GetMethod (MethodSignatures.GetObjectData); if (getObjectData == null) { // no GetObjectData means that the type's ancestor does the job but // are we introducing new instance fields that need to be serialized ? if (!type.HasFields) return RuleResult.Success; // there are some, but they could be static foreach (FieldDefinition field in type.Fields) { if (!field.IsStatic) Runner.Report (field, Severity.Medium, Confidence.High); } } else { if (type.HasFields) CheckUnusedFieldsIn (type, getObjectData); if (!type.IsSealed && getObjectData.IsFinal) { string msg = "Either seal this type or change GetObjectData method to be virtual"; Runner.Report (getObjectData, Severity.High, Confidence.Total, msg); } } return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule does not apply to enums, delegates and to generated code if (type.IsEnum || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; // rule applies only if the type overrides Equals(object) if (!type.HasMethod (MethodSignatures.Equals)) return RuleResult.DoesNotApply; // if so then the type should also implement Equals(type) since this avoid a cast // operation (for reference types) and also boxing (for value types). // we suggest to implement IEquatable<T> if // * the assembly targets the 2.0 (or later) runtime // * and it does not already implement it if (type.Module.Runtime >= TargetRuntime.Net_2_0) { if (!type.Implements ("System", "IEquatable`1")) { Runner.Report (type, Severity.Medium, Confidence.Total, "Implement System.IEquatable<T>"); } return Runner.CurrentRuleResult; } parameters [0] = type.GetFullName (); if (type.GetMethod (MethodAttributes.Public, "Equals", "System.Boolean", parameters) != null) return RuleResult.Success; // we consider this a step more severe for value types since it will need // boxing/unboxing with Equals(object) Severity severity = type.IsValueType ? Severity.Medium : Severity.Low; string msg = String.Format (CultureInfo.InvariantCulture, "Implement 'bool Equals({0})'", type.Name); Runner.Report (type, severity, Confidence.High, msg); return RuleResult.Failure; }
private static bool DoesTypeStealthilyImplementInterface (TypeDefinition type, TypeDefinition iface) { //ignore already uninteresting types below (self, enum, struct, static class) if (type == iface || type.IsEnum || type.IsValueType || type.IsStatic ()) return false; //if type has less methods than the interface no need to check further if (!type.HasMethods) return false; IList<MethodDefinition> mdc = iface.Methods; if (type.Methods.Count < mdc.Count) return false; //type already publicly says it implements the interface if (type.Implements (iface.Namespace, iface.Name)) return false; foreach (MethodDefinition m in mdc) { // FIXME: ignore methods with generic constraints if (HasConstraints (m)) return false; //if any candidate fails we can return right away //since the interface will never be fully implemented MethodDefinition candidate = type.GetMethod (MethodAttributes.Public, m.Name); if (null == candidate || !candidate.IsPublic || candidate.IsStatic) return false; //ok interesting candidate! let's check if it matches the signature if (!m.CompareSignature (candidate)) return false; // FIXME: ignore methods with generic constraints if (HasConstraints (candidate)) return false; } if (iface.HasInterfaces) { foreach (TypeReference tr in iface.Interfaces) { TypeDefinition td = tr.Resolve (); if (td == null) continue; if (!DoesTypeStealthilyImplementInterface (type, td)) return false; } } return true; }
public RuleResult CheckType(TypeDefinition type) { // rule does not apply to interfaces, delegates or types that does not implement ISerializable if (type.IsInterface || type.IsDelegate () || !type.Implements ("System.Runtime.Serialization", "ISerializable")) return RuleResult.DoesNotApply; // rule applies, only Success or Failure from the point on // check if the type implements the serialization constructor MethodDefinition ctor = type.GetMethod (MethodSignatures.SerializationConstructor); if (ctor == null) { // no serialization ctor Runner.Report (type, Severity.High, Confidence.Total, NoSerializationCtorText); return RuleResult.Failure; } else if (type.IsSealed) { // with ctor: on a sealed type the ctor must be private if (!ctor.IsPrivate) { Runner.Report (type, Severity.Low, Confidence.Total, CtorSealedTypeText); return RuleResult.Failure; } } else { // with ctor: on a unsealed type the ctor must be family if (!ctor.IsFamily) { Runner.Report (type, Severity.Low, Confidence.Total, CtorUnsealedTypeText); return RuleResult.Failure; } } // everything is fine return RuleResult.Success; }
public RuleResult CheckType (TypeDefinition type) { MethodDefinition finalizer = type.GetMethod (MethodSignatures.Finalize); if (finalizer == null) // no finalizer found return RuleResult.DoesNotApply; // good finalizer: if (finalizer.IsFamily && !finalizer.IsFamilyAndAssembly && !finalizer.IsFamilyOrAssembly) return RuleResult.Success; Runner.Report (finalizer, Severity.High, Confidence.Total); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { if (!type.IsClass || !type.HasMethods || !type.Inherits ("System.Windows.FrameworkElement")) return RuleResult.DoesNotApply; var arrangeOverride = type.GetMethod (arrangeSignature); var measureOverride = type.GetMethod (measureSignature); // The class doesn't have either method. if (arrangeOverride == null && measureOverride == null) return RuleResult.DoesNotApply; // Only ArrangeOverride provided. if (arrangeOverride != null && measureOverride == null) Runner.Report (arrangeOverride, Severity.High, Confidence.Total); // Only MeasureOverride provided. if (measureOverride != null && arrangeOverride == null) Runner.Report (measureOverride, Severity.High, Confidence.Total); return Runner.CurrentRuleResult; }
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 ("Contains {0} fields being nullified needlessly", nullify_fields); Runner.Report (type, Severity.Medium, Confidence.Normal, msg); return RuleResult.Failure; }
public RuleResult CheckType (TypeDefinition type) { // rule doesn't apply to enums, interfaces, structs, delegates or generated code if (type.IsEnum || type.IsInterface || type.IsValueType || type.IsDelegate () || type.IsGeneratedCode ()) return RuleResult.DoesNotApply; MethodDefinition explicitDisposeMethod = null; MethodDefinition implicitDisposeMethod = null; bool abstractWarning = false; if (type.Implements ("System.IDisposable")) { implicitDisposeMethod = type.GetMethod (MethodSignatures.Dispose); explicitDisposeMethod = type.GetMethod (MethodSignatures.DisposeExplicit); if (IsAbstract (implicitDisposeMethod) || IsAbstract (explicitDisposeMethod)) { abstractWarning = true; } else { return RuleResult.Success; } } foreach (FieldDefinition field in type.Fields) { // we can't dispose static fields in IDisposable if (field.IsStatic) continue; TypeDefinition fieldType = field.FieldType.GetElementType ().Resolve (); if (fieldType == null) continue; // enums and primitives don't implement IDisposable if (fieldType.IsEnum || fieldType.IsPrimitive) continue; if (fieldType.Implements ("System.IDisposable")) { Runner.Report (field, Severity.High, Confidence.High, abstractWarning ? AbstractTypeMessage : TypeMessage); } } // Warn about possible confusion if the Dispose methods are abstract if (IsAbstract (implicitDisposeMethod)) Runner.Report (implicitDisposeMethod, Severity.Medium, Confidence.High, AbstractDisposeMessage); return Runner.CurrentRuleResult; }
public RuleResult CheckType (TypeDefinition type) { // rule applies only to types that implements ISerializable if (!type.Implements ("System.Runtime.Serialization.ISerializable")) return RuleResult.DoesNotApply; MethodDefinition method = type.GetMethod (MethodSignatures.GetObjectData); if (method == null) return RuleResult.DoesNotApply; // *** ok, the rule applies! *** // is there any security applied ? if (!method.HasSecurityDeclarations) { Runner.Report (method, Severity.High, Confidence.Total, NotFound); return RuleResult.Failure; } // the SerializationFormatter must be a subset of the one (of the) demand(s) bool demand = false; foreach (SecurityDeclaration declsec in method.SecurityDeclarations) { switch (declsec.Action) { case Mono.Cecil.SecurityAction.Demand: case Mono.Cecil.SecurityAction.NonCasDemand: case Mono.Cecil.SecurityAction.LinkDemand: case Mono.Cecil.SecurityAction.NonCasLinkDemand: demand = true; if (!RuleSet.IsSubsetOf (declsec.ToPermissionSet ())) { string message = String.Format ("{0} is not a subset of {1} permission set", "SerializationFormatter", declsec.Action); Runner.Report (method, Severity.High, Confidence.Total, message); } break; } } // there was no [NonCas][Link]Demand but other actions are possible if (!demand) Runner.Report (method, Severity.High, Confidence.Total, NotFound); return Runner.CurrentRuleResult; }
protected void WeaveTypeProperties(TypeDefinition type) { var properties = type.Properties.Where( p => p.CustomAttributes.Any( a => a.AttributeType.FullName == typeof (PropertyAttribute).FullName)); if(!properties.Any()) return; if(!type.HasInterface(typeof(IPropertyNotifier).FullName)) throw new Exception(string.Format("Type {0} has properties but does not implement {1}", type.FullName, typeof(IPropertyNotifier).FullName)); Console.WriteLine(type.FullName); var weaver = new TypeWeaver(originType, type); foreach(var property in properties) { weaver.NamePrefix = "<$" + property.Name + "$>"; var desNotifierMethod = type.GetMethod(tNotifierMethod.Name); weaver.Map(tNotifierMethod, desNotifierMethod); var propField = weaver.AddDefinition(tPropertyField); propField.FieldType = property.PropertyType; weaver.AddConstant(tPropertyNameC,property.Name); //TODO delete property generated field weaver.Merge(tPropertyProperty, property); weaver.ProcessInstructions(); } }
public RuleResult CheckType(TypeDefinition type) { // rule does not apply to enums, interfaces and delegates if (type.IsEnum || type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; // rule applies to types that implements System.IDisposable if (!type.Implements ("System", "IDisposable")) return RuleResult.DoesNotApply; // and provide a finalizer if (type.GetMethod (MethodSignatures.Finalize) == null) return RuleResult.DoesNotApply; // rule applies! // look if GC.SuppressFinalize is being called in the Dispose methods // or one of the method it calls CheckDispose (type.GetMethod (MethodSignatures.Dispose)); CheckDispose (type.GetMethod (MethodSignatures.DisposeExplicit)); return Runner.CurrentRuleResult; }
private static bool DoesTypeStealthilyImplementInterface (TypeDefinition type, TypeReference iface) { //ignore already uninteresting types below (self, enum, struct, static class) if (type == iface || type.IsEnum || type.IsValueType || type.IsStatic ()) return false; //if type has less methods than the interface no need to check further if (!type.HasMethods) return false; IList<MethodDefinition> mdc = iface.GetMethods ().ToList (); if (type.Methods.Count < mdc.Count) return false; //type already publicly says it implements the interface if (type.Implements (iface.FullName)) return false; foreach (MethodDefinition m in mdc) { //if any candidate fails we can return right away //since the interface will never be fully implemented MethodDefinition candidate = type.GetMethod (MethodAttributes.Public, m.Name); if (null == candidate || !candidate.IsPublic || candidate.IsStatic) return false; //ok interesting candidate! let's check if it matches the signature if (!AreSameElementTypes (m.ReturnType, candidate.ReturnType)) return false; if (!CompareParameters (m, candidate)) return false; } return true; }
public RuleResult CheckType (TypeDefinition type) { if (type.IsEnum || type.IsInterface || type.IsDelegate ()) return RuleResult.DoesNotApply; foreach (var kv in AlternativeMethodNames) { MethodDefinition op = type.GetMethod (kv.Key); if (op == null) continue; bool alternativeDefined = false; foreach (MethodDefinition alternative in type.Methods) { if (kv.Value.Matches (alternative)) { alternativeDefined = true; break; } } if (!alternativeDefined) { string s = String.Format ("This type implements the '{0}' operator. Some languages do not support overloaded operators so an alternative '{1}' method should be provided.", kv.Key.Name, kv.Value.Name); Runner.Report (op, Severity.Medium, Confidence.High, s); } } return Runner.CurrentRuleResult; }
private MethodDefinition CacheTypeGetContainsMethod(TypeDefinition cacheType, string cacheTypeContainsMethodName) { return cacheType.GetMethod(cacheTypeContainsMethodName, cacheType.Module.ImportType<bool>(), new[] { cacheType.Module.ImportType<string>() }); }
public void FixtureSetUp () { string unit = System.Reflection.Assembly.GetExecutingAssembly ().Location; type_def = AssemblyDefinition.ReadAssembly (unit).MainModule.GetType ("Test.Framework.Rocks.InstructionRocksTest"); body = type_def.GetMethod ("Fields").Body; }