Ejemplo n.º 1
0
		public static void ProcessCallOrNewobj(MethodInfoExtention method,StackTypes stack, bool isNewObj)
		{
			for(int i = method.ArgCount-1; i >= (isNewObj ? 1 : 0); i--) 
			{ //when we are creating a new object `this` is not on stack
				TypeEx sourceType = stack.Pop();
				TypeEx targetType = method.GetArgType(i);
				TypeChecker.CheckAssignment(targetType, sourceType);
			}
			TypeEx returnType = method.GetReturnType();
			if(isNewObj)
				stack.Push(method.DeclaringType);
				//Wow! Value-types can be created on stack with NEWOBJ instruction -- not boxed
			else if(!returnType.type.Equals(typeof(void)))
				stack.Push(returnType);
		}
Ejemplo n.º 2
0
		internal static bool Check(MethodEx methodRepr)
		{
			//Attention: the `null` value on stack means a null reference that is of any object type 
			//As `typeof(object)` is the most general Type, so `null` is the most exact object type 
			FreeStacks(methodRepr);
			try
			{
				Instruction lastI = methodRepr[methodRepr.Count-1]; 
				if(    lastI.Code != InstructionCode.RET 
					&& lastI.Code != InstructionCode.BR
					&& lastI.Code != InstructionCode.THROW
					&& lastI.Code != InstructionCode.RETHROW
					&& lastI.Code != InstructionCode.LEAVE
					&& lastI.Code != InstructionCode.ENDFINALLY
					&& lastI.Code != InstructionCode.ENDFILTER )
						throw new VerifierException();
				MethodInfoExtention method = new MethodInfoExtention(methodRepr.Method);
				StackTypes stack = new StackTypes(); //initially the stack is empty
				int nextHandler = FindNextHandler(-1,methodRepr.EHClauses);
				CheckBlockExits(methodRepr);
				for (int iNum = 0; iNum < methodRepr.Count ; iNum ++)
				{  
					Instruction i = methodRepr[iNum]; 
					i.SetStack(MergeStacks(i.Stack,stack));
					if(nextHandler == iNum)
					{
						PushExceptionOnStack(iNum,i.Stack,methodRepr.EHClauses);
						nextHandler = FindNextHandler(iNum,methodRepr.EHClauses);
					}
					stack = i.Stack.Clone() as StackTypes;  
					switch(i.Code)
					{
						case InstructionCode.DUP :    
						{
							stack.Push(stack.Peek()); 
						} break;
						case InstructionCode.LDARG : 
						{
							stack.Push(method.GetArgType((Int32)i.Param));
						} break;
						case InstructionCode.LDARGA : 
						{
							TypeEx t = method.GetArgType((Int32)i.Param).BuildRefType();
							stack.Push(t);
						} break;
						case InstructionCode.LDLOCA : 
						{
							TypeEx t = new TypeEx(TypeEx.BuildRefType(methodRepr.Locals[(Int32)i.Param]));
							stack.Push(t);
						} break;
						case InstructionCode.LDLOC : 
						{
							stack.Push(new TypeEx(methodRepr.Locals[(Int32)i.Param]));
						} break;
						case InstructionCode.LDIND :
						{
							ProcessLdInd(i.TypeBySuffixOrParam(), stack);
						} break;
						case InstructionCode.LDC:
						{
							stack.Push(new TypeEx(i.TypeBySuffixOrParam()));
						} break;
						case InstructionCode.LDNULL:
						{
							stack.Push(new TypeEx(null));//see `Attention` at the top of the method.
						} break;
						case InstructionCode.LDFLD:
						{
							ProcessLdFld(stack, i.Param as FieldInfo,false);
						} break;
						case InstructionCode.LDFLDA:
						{
							ProcessLdFld(stack, i.Param as FieldInfo,true);
						} break;
						case InstructionCode.LDSFLD:
						{
							stack.Push(new TypeEx((i.Param as FieldInfo).FieldType)); 
						} break;
						case InstructionCode.LDSFLDA:
						{
							stack.Push(TypeEx.BuildRefType((i.Param as FieldInfo).FieldType)); 
						} break;
						case InstructionCode.LDELEM:
						{
							ProcessLdElem(stack, new TypeEx(i.TypeBySuffixOrParam()), false);
						} break;
						case InstructionCode.LDELEMA:
						{
							ProcessLdElem(stack, new TypeEx(i.TypeBySuffixOrParam()), true);
						} break;
						case InstructionCode.LDLEN :
						{
							ProcessLdLen(stack);
						} break;
						case InstructionCode.LDOBJ :
						{
							ProcessLdObj(stack, i.Param as Type);
						} break;
						case InstructionCode.LDSTR:
						{
							if(!(i.Param is string)) 
								throw new VerifierException();
							stack.Push(typeof(string));
						} break;
						case InstructionCode.LDFTN:
						{
							stack.Push(new TypeEx(typeof(IntPtr))); 
						} break;
						case InstructionCode.LDVIRTFTN:
						{
							TypeEx obj = stack.Pop();
							MethodInfo methodInfo = i.Param as MethodInfo;
							if(!methodInfo.IsVirtual)
								throw new VerifierException();
							TypeChecker.CheckAssignment(new TypeEx(methodInfo.DeclaringType , true), obj);
							stack.Push(typeof(IntPtr));
						} break;
						case InstructionCode.LDTOKEN:
						{
							if(i.Param is Type)
								stack.Push(typeof(System.RuntimeTypeHandle));
							else if(i.Param is MethodBase)
								stack.Push(typeof(System.RuntimeMethodHandle));
							else if(i.Param is FieldInfo)
								stack.Push(typeof(System.RuntimeFieldHandle));
							else
								throw new VerifierException();
						} break;
						case InstructionCode.SIZEOF :
						{
							ProcessSizeOf(stack,i.Param as Type);
						} break;

						case InstructionCode.CLT: 
						case InstructionCode.CGT:
						case InstructionCode.CEQ:
						{
              ProcessBinOp(OpType.Compare,stack);
						} break;

						case InstructionCode.BLE:
						case InstructionCode.BLT: 
						case InstructionCode.BGE:
						case InstructionCode.BGT:
						case InstructionCode.BEQ:
						case InstructionCode.BNE:
						{
							TypeEx t1 = stack.Pop();
							TypeEx t2 = stack.Pop();
							Arithmetics.CheckTypes(t1,t2);
							ProcessBr(iNum,methodRepr,stack);
							stack = stack.Clone() as StackTypes; 
							//Andrew: mb wrong, we may let equal stacks to be the same object
						} break;
						case InstructionCode.BRTRUE:
						case InstructionCode.BRFALSE:
						{
							ProcessBrTrueFalse(stack);
							ProcessBr(iNum,methodRepr,stack);
							stack = stack.Clone() as StackTypes; 
							//Andrew: mb wrong, we may let equal stacks to be the same object
						} break;
						case InstructionCode.BR : 
						{
							ProcessBr(iNum,methodRepr,stack);
							stack = null; 
						} break;

						case InstructionCode.SWITCH:
						{
							ProcessSwitch(stack);
							ProcessSwitch(iNum,methodRepr,stack);
							stack = stack.Clone() as StackTypes; 
						} break;
            
						case InstructionCode.THROW :
						{
							ProcessThrow(stack);
							stack = null;
						}break;
            
						case InstructionCode.RETHROW :
						{
							if(GetNearestBlock(methodRepr.EHClauses,iNum).type != BlockType.Catch)
								throw new VerifierException();
							stack = null;
						}break;

						case InstructionCode.LEAVE : 
						{
							BlockType blockType = GetNearestBlock(methodRepr.EHClauses,iNum).type;
							if(blockType != BlockType.Catch && blockType != BlockType.Try)
								throw new VerifierException();
							ProcessLeave(iNum,methodRepr,stack);
							stack = null; 
						} break;

						case InstructionCode.ENDFINALLY : 
						{ 
							if(GetNearestBlock(methodRepr.EHClauses,iNum).type != BlockType.Finally)
								throw new VerifierException();
							ProcessLeave(stack);
							stack = null; 
						} break;

						case InstructionCode.ENDFILTER : 
						{ 
							if(GetNearestBlock(methodRepr.EHClauses,iNum).type != BlockType.Filter)
								throw new VerifierException();
							ProcessEndFilter(stack);
							stack = null; 
						} break;

						case InstructionCode.NOT:
						{
							ProcessNot(stack);
						} break;

						case InstructionCode.NEG:
						{
							ProcessNeg(stack);
						} break;
              
						case InstructionCode.CKFINITE :
						{ 
							ProcessCkFinite(stack);
						} break;

						case InstructionCode.CONV:
						{
							ProcessConv(i.TypeBySuffixOrParam(), stack);
						} break;

						case InstructionCode.SUB: 
						case InstructionCode.ADD: 
						case InstructionCode.MUL: 
						case InstructionCode.DIV: 
						case InstructionCode.REM: 
						case InstructionCode.XOR:
						case InstructionCode.OR:
						case InstructionCode.AND:
						{
							ProcessBinOp(IsFloatOperation(i) ? OpType.FloatOrInt : OpType.Int , stack);
						} break;

						case InstructionCode.SHL:
						case InstructionCode.SHR:
						{
							ProcessBinOp(OpType.Shift , stack);
						} break;

						case InstructionCode.CPOBJ :
						{
							ProcessCpObj(stack, i.Param as Type);
						} break;

						case InstructionCode.STARG : 
						{
							ProcessSt(method.GetArgType((Int32)i.Param) , stack);
						} break;
						case InstructionCode.STLOC : 
						{
							ProcessSt(new TypeEx(methodRepr.Locals[(Int32)i.Param]) , stack);
						} break;
						case InstructionCode.STIND :
						{
							ProcessStInd(i.TypeBySuffixOrParam() , stack);
						} break;
						case InstructionCode.STFLD:
						{
							ProcessStFld(stack, i.Param as FieldInfo);
						} break;
						case InstructionCode.STSFLD:
						{
							ProcessStSFld(stack, i.Param as FieldInfo);
						} break;
						case InstructionCode.STELEM:
						{
							ProcessStElem(stack, new TypeEx(i.TypeBySuffixOrParam()));
						} break;
						case InstructionCode.STOBJ :
						{
							ProcessStObj(stack, i.Param as Type);
						} break;

						case InstructionCode.RET : 
						{
							if(GetNearestBlock(methodRepr.EHClauses,iNum).type != BlockType.Global)
								throw new VerifierException();
							ProcessRet(method.GetReturnType(), stack);
							stack = null;  
						} break;
						case InstructionCode.CALL : 
						case InstructionCode.CALLVIRT :
						case InstructionCode.NEWOBJ :
						{
							//constructor may be invoked using either CALL or NEWOBJ instructions
							MethodBase callee = i.Param as MethodBase; 
							if(i.Code == InstructionCode.NEWOBJ && callee.IsConstructor && IsDelegate(callee.DeclaringType))
								ProcessDelegateConstruction(methodRepr,iNum,stack);
							else
							  ProcessCallOrNewobj(new MethodInfoExtention(callee,i.Code == InstructionCode.CALLVIRT), stack, i.Code == InstructionCode.NEWOBJ);
                            if(i.HasTail && methodRepr[iNum+1].Code != InstructionCode.RET)
								throw new VerifierException();
						} break;
						case InstructionCode.INITOBJ :
						{
							ProcessInitObj(stack, i.Param as Type);
						} break;
						case InstructionCode.NEWARR :
						{
							ProcessNewArr(stack, i.Param as Type);
						} break;
						case InstructionCode.ISINST :
						case InstructionCode.CASTCLASS :
						{
							ProcessCastClass(stack, new TypeEx(i.Param as Type , true));
						} break;

						case InstructionCode.BOX :
						{
							ProcessBox(stack, i.Param as Type);
						} break;

						case InstructionCode.UNBOX :
						{
							ProcessUnBox(stack, i.Param as Type);
						} break;

						case InstructionCode.POP :
						{
							stack.Pop(); 
						} break;

						case InstructionCode.NOP :
						case InstructionCode.BREAK :
							break;

						default: 
						{
							throw new VerifierException();
							//Instruction is not supported yet...
						}
					}  
				}
				return(true);
			}
			catch(VerifierException )
			{ 
				FreeStacks(methodRepr);
				return(false);
			}
			//catch(NullReferenceException ) //Andrew: ZaLyaPa :( waiting for Sergey to patch NEWOBJ (delegate construction)
			//{
			//	FreeStacks(methodRepr);
			//	return(false);
			//}
		}