Exemplo n.º 1
0
		/// <summary>Returns true if we're calling an instance method with caller's this
		/// pointer, or if we're calling a static method in caller's declaring
		/// type with caller's this pointer as an argument.</summary>
		public bool IsThisCall(AssemblyCache cache, MethodInfo caller, int callIndex)
		{
			DBC.Pre(cache != null, "cache is null");				
			DBC.Pre(caller != null, "caller is null");
				
			if (!m_isThisCall.HasValue)
			{
				m_isThisCall = false;

				MethodInfo target = cache.FindMethod(Target);
				if (target != null && !target.Method.IsConstructor)
				{
					if (target.Method.HasThis)
					{
						int nth = target.Method.Parameters.Count;
						int j = caller.Tracker.GetStackIndex(callIndex, nth);
						
						if (j >= 0)
							m_isThisCall = caller.Instructions.LoadsThisArg(j);
					}
					else if (target.Method.IsStatic)
					{
						for (int i = 0; i < target.Method.Parameters.Count && !m_isThisCall.Value; ++i)
						{
							int j = caller.Tracker.GetStackIndex(callIndex, i);				

							if (j >= 0)
								m_isThisCall = caller.Instructions.LoadsThisArg(j);
						}
					}
				}
			}
			return m_isThisCall.Value;
		}
Exemplo n.º 2
0
		private bool DoChecksState(MethodInfo info)	
		{
			bool usesStates = false;
			Log.DebugLine(this, "checking:", info.Instructions);	
			Log.DebugLine(this, "{0:F}", info.Instructions);	
			
			for (int i = 1; i < info.Instructions.Length && !usesStates; ++i)
			{
				Code code = info.Instructions[i].Untyped.OpCode.Code;
				if (code == Code.Ldfld || code == Code.Ldflda)
				{	
					if (info.Instructions[i - 1].Untyped.OpCode.Code == Code.Ldarg_0)
					{
						usesStates = true;
					}
				}
				else if (code == Code.Call || code == Code.Callvirt)
				{
					string name = ((MethodReference) info.Instructions[i].Untyped.Operand).Name;
					if (name.StartsWith("get_"))
					{	
						if (info.Instructions[i - 1].Untyped.OpCode.Code == Code.Ldarg_0)
						{
							usesStates = true;
						}
					}
				}
			}

			return usesStates;
		}
Exemplo n.º 3
0
		private int DoCallsVirtual(AssemblyCache cache, MethodInfo info)
		{
			int offset = -1;
			if (m_tested.IndexOf(info.Method.ToString()) >= 0)
				return offset;
				
			m_tested.Add(info.Method.ToString());

			Log.DebugLine(this, "checking:");
			Log.Indent();
			
			// If the class isn't sealed then,
			if (info.Method.Body != null && info.Instructions != null)
			{
				Log.DebugLine(this, "{0:F}", info.Instructions);

				// loop through every instruction,
				for (int i = 0; i < info.Instructions.Length && offset < 0; ++i)
				{
					// if it's a call,
					Call call = info.Instructions[i] as Call;
					if (call != null)
					{	
						// then we have a problem if we're calling a virtual method
						// on our instance,
						MethodInfo targetInfo = cache.FindMethod(call.Target);
						if (targetInfo != null)
						{
							if (call.IsThisCall(Cache, info, i))
							{
								if (targetInfo.Method.IsVirtual && !targetInfo.Method.IsFinal)
								{
									Log.DebugLine(this, "{0} is virtual", call.Target);
									{
										m_details = call.Target.ToString();			
										offset = call.Untyped.Offset;
										Log.DebugLine(this, "found virtual call at {0:X2}", offset);
									}
								}
								else
								{
									// or we're calling one of our methods which calls a virtual method
									// on our instance.
									offset = DoCallsVirtual(cache, targetInfo);
								}
							}
						}
					}
				}
			}
			Log.Unindent();
			
			if (offset >= 0)
				m_details = info.Method + " -> " + Environment.NewLine + "       " + m_details;			
			
			return offset;
		}
Exemplo n.º 4
0
		/// <summary>Returns the index of the instruction which pushed the method call's
		/// this argument onto the stack. May return -1 if a single such instruction
		/// could not be found.</summary>
		public int GetThisIndex(MethodInfo info)
		{
			DBC.Pre(info != null, "info is null");
			DBC.Pre(Target.HasThis, "the method is static");
			
			if (!m_thisIndex.HasValue)
				m_thisIndex = info.Tracker.GetStackIndex(Index, Target.Parameters.Count);
			
			return m_thisIndex.Value;
		}
Exemplo n.º 5
0
		private void DoCheck(MethodInfo info)
		{
			if (info.Instructions.Length == 2)
			{
				LoadConstantInt load = info.Instructions[0] as LoadConstantInt;
				End end = info.Instructions[1] as End;
				
				if (load != null && end != null && end.Untyped.OpCode.Code == Code.Ret)
				{
					Log.DebugLine(this, "returns constant");
					Reporter.MethodFailed(info.Method, CheckID, 0, string.Empty);
				}
			}
		}
Exemplo n.º 6
0
        private void DoVisit(RuleDispatcher dispatcher, TypeDefinition type)
        {
            dispatcher.Dispatch(type);

            // Some rules consider all the methods in a type. These rules cannot be tested
            // with a MethodTest so we'll visit methods here in order to be able to unit
            // test those rules.
            dispatcher.Dispatch(new BeginMethods(type));
            foreach (MethodDefinition method in type.Constructors)
            {
                var minfo = new Smokey.Framework.Support.MethodInfo(type, method);
                dispatcher.Dispatch(minfo);
            }
            foreach (MethodDefinition method in type.Methods)
            {
                var minfo = new Smokey.Framework.Support.MethodInfo(type, method);
                dispatcher.Dispatch(minfo);
            }
            dispatcher.Dispatch(new EndMethods(type));
        }
Exemplo n.º 7
0
		private void DoCheckMethod(MethodInfo info)
		{			
			if (DoObjectRequiresCheck(info.Method.ToString()))
			{
				m_callback(info.Method.ToString());
				m_dispatcher.Dispatch(info);
			}
		}
Exemplo n.º 8
0
		public void Check(MethodInfo method)
		{			
			if (method.Method.Body != null)
				DoCheckMethod(method);
		}
Exemplo n.º 9
0
		public static bool IsIntOperand(MethodInfo info, int index, int nth)
		{
			bool isInt = false;
			
			int i = info.Tracker.GetStackIndex(index, nth);
			if (i >= 0)
			{
				do
				{
					LoadArg arg = info.Instructions[i] as LoadArg;
					if (arg != null && arg.Arg >= 1)
					{
						ParameterDefinition p = info.Method.Parameters[arg.Arg - 1];
						if (p.ParameterType.FullName == "System.Int32")
							isInt = true;
						break;
					}

					LoadConstantInt constant = info.Instructions[i] as LoadConstantInt;
					if (constant != null)
					{
						Code code = constant.Untyped.OpCode.Code;
						switch (code)
						{
							case Code.Ldc_I4_M1:
							case Code.Ldc_I4_0:
							case Code.Ldc_I4_1:
							case Code.Ldc_I4_2:
							case Code.Ldc_I4_3:
							case Code.Ldc_I4_4:
							case Code.Ldc_I4_5:
							case Code.Ldc_I4_6:
							case Code.Ldc_I4_7:
							case Code.Ldc_I4_8:
							case Code.Ldc_I4_S:
							case Code.Ldc_I4:
								isInt = true;
								break;
						}
						break;
					}

					LoadField field = info.Instructions[i] as LoadField;
					if (field != null)
					{
						if (field.Field.FieldType.FullName == "System.Int32")
							isInt = true;
						break;
					}

					LoadLocal local = info.Instructions[i] as LoadLocal;
					if (local != null)
					{
						VariableDefinition v = info.Method.Body.Variables[local.Variable];
						if (v.VariableType.FullName == "System.Int32")
							isInt = true;
						break;
					}

					LoadStaticField sfield = info.Instructions[i] as LoadStaticField;
					if (sfield != null)
					{
						if (sfield.Field.FieldType.FullName == "System.Int32")
							isInt = true;
						break;
					}
				} 
				while (false);	
			}
			
			return isInt;
		}
Exemplo n.º 10
0
		private bool DoMethodCallsNoInstanceMethods(MethodInfo info)
		{
			bool foundCall = false;
				
			for (int i = 1; i < info.Instructions.Length && !foundCall; ++i)
			{
				Call call = info.Instructions[i] as Call;
				if (call != null && !call.Target.Name.StartsWith("get_"))
				{	
					MethodInfo targetInfo = Cache.FindMethod(call.Target);
					if (targetInfo != null)
					{
						if (call.IsThisCall(Cache, info, call.Index))
						{
							Log.DebugLine(this, "{0} at {1:X2} is a this call", call.Target.Name, call.Untyped.Offset);
							foundCall = true;
						}
					}
					
					// Special case operator== calling Object.Equals with this arg.
					else if (info.Method.Name == "op_Equality")
					{
						if (call.Target.ToString().Contains("System.Object::Equals"))
						{
							if (info.Instructions[i - 1].Untyped.OpCode.Code == Code.Ldarg_0 || info.Instructions[i - 2].Untyped.OpCode.Code == Code.Ldarg_0)
							{
								Log.DebugLine(this, "{0} at {1:X2} is calling Object.Equals with this", call.Target.Name, call.Untyped.Offset);
								foundCall = true;
							}
						}
					}
					
					// Generics suck: when we call a generic method or a method in a generic type we're
					// calling an instantiated version of the method which has a different token. To avoid
					// false positives we need to set foundCall to true so we'll hack up a test here.
					else
					{
						string name = call.Target.ToString();
						int j = name.IndexOf(':');
						if (name.Contains("<") && name.Contains(">") && j > 0)
						{
							name = name.Substring(0, j);
							if (name.Contains(info.Type.FullName))
							{
								foundCall = true;
								Log.DebugLine(this, "{0} at {1:X2} seems to be a generic my call", call.Target.Name, call.Untyped.Offset);
							}
						}
					}
				}
			}
			
			return !foundCall;
		}
Exemplo n.º 11
0
		private void DoAddReference(Dictionary<MethodInfo, List<string>> references, MethodInfo info, string name, int offset)
		{
			List<string> names;
			if (!references.TryGetValue(info, out names))
			{
				names = new List<string>();
				references.Add(info, names);
			}
			
			if (names.IndexOf(name) < 0)
			{
				Log.DebugLine(this, "found {0} at {1:X2} for {2}", name, offset, info.Method.Name);
				names.Add(name);
			}
		}
Exemplo n.º 12
0
		private void DoGetReferences(Dictionary<MethodInfo, List<string>> references, MethodInfo info)
		{
			for (int i = 1; i < info.Instructions.Length; ++i)
			{
				do
				{
					LoadField field = info.Instructions[i] as LoadField;
					if (field != null)
					{	
						if (info.Instructions.LoadsThisArg(i - 1))
							DoAddReference(references, info, field.Field.Name, field.Untyped.Offset);
						break;
					}

					LoadFieldAddress addr = info.Instructions[i] as LoadFieldAddress;
					if (addr != null)
					{
						if (info.Instructions.LoadsThisArg(i - 1))
							DoAddReference(references, info, addr.Field.Name, addr.Untyped.Offset);
						break;
					}
				
					Call call = info.Instructions[i] as Call;
					if (call != null && call.Target.Name.StartsWith("get_"))
					{	
						if (info.Instructions.LoadsThisArg(i - 1))
							DoAddReference(references, info, call.Target.Name, call.Untyped.Offset);
						break;
					}
				}
				while (false);
			}
		}
Exemplo n.º 13
0
        private void DoVisit(RuleDispatcher dispatcher, TypeDefinition type)
        {
            dispatcher.Dispatch(type);

            // Some rules consider all the methods in a type. These rules cannot be tested
            // with a MethodTest so we'll visit methods here in order to be able to unit
            // test those rules.
            dispatcher.Dispatch(new BeginMethods(type));
            foreach (MethodDefinition method in type.Constructors)
            {
                var minfo = new Smokey.Framework.Support.MethodInfo(type, method);
                dispatcher.Dispatch(minfo);
            }
            foreach (MethodDefinition method in type.Methods)
            {
                var minfo = new Smokey.Framework.Support.MethodInfo(type, method);
                dispatcher.Dispatch(minfo);
            }
            dispatcher.Dispatch(new EndMethods(type));
        }
Exemplo n.º 14
0
		public CodeBlock(MethodInfo info, int index)
		{
			Method = info.Method;
			Instructions = info.Instructions;
			Index = index;
		}
Exemplo n.º 15
0
		private static bool DoNeedsCheck(MethodInfo info)
		{
			bool needs = false;
			
			if (!info.Method.IsStatic && !info.Method.IsVirtual)
			{
				if (!info.Method.ToString().Contains("CompilerGenerated") && !info.Method.ToString().Contains("_AnonymousMethod"))
				{
					if (!info.Type.Namespace.StartsWith("System") && !info.Type.Namespace.StartsWith("Mono"))
					{
						needs = true; 
					}
					
					// If the type is in the System or Mono namespaces then it can only
					// be made static if it's access is private or internal to the assembly.
					else if ((info.Method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
					{
						needs = true;
					}
					else if ((info.Method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem)
					{
						needs = true;
					}
				}
			}
			
			return needs;
		}
Exemplo n.º 16
0
		// Returns the smallest number k such that the instructions in
		// [offset - k, offset] push a single value onto the stack.
		private int DoGetPushRange(MethodInfo info, int offset)
		{
			int delta = DoGetStackDelta(info.Instructions[offset]);
			
			int k = 0;
			while (delta <= 0 && offset - k >= 0)
			{
				++k;
				delta += DoGetStackDelta(info.Instructions[offset - k]);
			}
			
			DBC.Assert(offset - k >= 0, "couldn't find the range");
			
			return k;
		}
Exemplo n.º 17
0
			public MethodCapture(MethodInfo info)
			{
				Method = info.Method;
				Instructions = info.Instructions;
			}