public static void ProcessBox(StackTypes stack, Type T) { TypeEx valueType = stack.Pop(); if(! valueType.IsBoxable || valueType.boxed) throw new VerifierException(); TypeChecker.CheckAssignment(new TypeEx(T), valueType); // Skor >> this code was wrong ! //stack.Push(new TypeEx(valueType.type , true )); stack.Push(new TypeEx(T, true)); }
public static void ProcessLdLen(StackTypes stack) { TypeEx array = stack.Pop(); if(!array.type.IsArray) throw new VerifierException(); stack.Push(typeof(int)); }
public static void ProcessCastClass(StackTypes stack, TypeEx t) { TypeEx T = stack.Pop(); if(T.IsBoxable && !T.boxed) throw new VerifierException(); stack.Push(t); }
static public void ProcessLdInd(Type T, StackTypes stack) { TypeEx addr = stack.Pop(); if(!addr.type.IsByRef) throw new VerifierException(); TypeEx sourceType = new TypeEx(addr.type.GetElementType()); TypeEx targetType = new TypeEx(T); if(targetType.type.Equals(typeof(object))) //.ref suffix stack.Push(sourceType); else { TypeChecker.CheckAssignment(targetType,sourceType); stack.Push(targetType); } }
public static void ProcessLdElem(StackTypes stack,TypeEx desiredArrayElem,bool loadAddress) { TypeEx index = stack.Pop(); TypeEx array = stack.Pop(); TypeEx arrayElem = ProcessLdStElem(array,desiredArrayElem,index); if(loadAddress) arrayElem = arrayElem.BuildRefType(); stack.Push(arrayElem); }
public static void ProcessNeg(StackTypes stack) { TypeEx t = stack.Pop(); if(!t.type.IsPrimitive || t.boxed) throw new VerifierException(); stack.Push(TypeFixer.FixType(t)); }
static public void ProcessSizeOf(StackTypes stack, Type t) { if(!t.IsValueType) throw new VerifierException(); stack.Push(typeof(int)); }
public static StackTypes DoMergeStacks(StackTypes s,StackTypes t) { //assert(s!=null && t!=null) if (s.Count != t.Count) throw new VerifierException(); //different lengths StackTypes u = new StackTypes(); for (int i = 0; i < s.Count; i++) { u.Push(TypeChecker.MergeTypes(s[i],t[i])); } return(u); }
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); }
static public void ProcessDelegateConstruction(StackTypes stack, MethodInfo ftn, ConstructorInfo ctor) { TypeEx obj = stack.Pop(); TypeChecker.CheckAssignment(new TypeEx(ftn.DeclaringType , true), obj); Type delegateType = ctor.DeclaringType; if(!IsDelegate(delegateType)) throw new VerifierException(); MethodInfo prototype = delegateType.GetMethod("Invoke"); if(!SameSignatures(prototype, ftn)) throw new VerifierException(); stack.Push(delegateType); }
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); //} }
static void PushExceptionOnStack(int iNum, StackTypes stack, EHClausesArray clauses) { foreach(EHClause c in clauses) { if(c.Kind == EHClauseKind.UserFilteredHandler) { if(c.FilterStart == iNum) { if(stack.Count != 0) throw new VerifierException(); stack.Push(new TypeEx(typeof(object))); return; } } if(c.HandlerStart == iNum) { if(stack.Count != 0) throw new VerifierException(); switch(c.Kind) { case EHClauseKind.FaultHandler: case EHClauseKind.UserFilteredHandler: { stack.Push(new TypeEx(typeof(object))); } break; case EHClauseKind.TypeFilteredHandler: { stack.Push(new TypeEx(c.ClassObject)); } break; } return; } } }
static public void ProcessConv(Type T, StackTypes stack) { TypeEx t = stack.Pop(); if(!t.type.IsPrimitive || t.boxed ) throw new VerifierException(); stack.Push(T); }
static public void ProcessCkFinite(StackTypes stack) { TypeEx t = stack.Pop(); if(!TypeFixer.IsFloatOrCompatible(t) || t.boxed ) throw new VerifierException(); stack.Push(t); }
public static void ProcessUnBox(StackTypes stack, Type T) { TypeEx objType = stack.Pop(); Type valueType = T; if(! ((objType.IsBoxable && objType.boxed) || !objType.IsBoxable) ) throw new VerifierException(); if(! valueType.IsValueType ) throw new VerifierException(); stack.Push( TypeEx.BuildRefType(valueType) ); }
public static void ProcessNewArr(StackTypes stack, Type T) { TypeEx t = stack.Pop(); if(!TypeFixer.IsInt32OrCompatible(t) && !TypeFixer.IsIntPtrOrCompatible(t)) throw new VerifierException(); stack.Push( TypeEx.BuildArrayType(T) ); }
public static void ProcessNot(StackTypes stack) { TypeEx t = stack.Pop(); if(!t.type.IsPrimitive || t.boxed || TypeFixer.IsFloatOrCompatible(t)) throw new VerifierException(); stack.Push(TypeFixer.FixType(t)); }
public static void ProcessLdFld(StackTypes stack, FieldInfo field, bool loadAddress) { TypeEx obj = stack.Pop(); if(obj.type != null) //LDNULL LDFLD -- crazy! { if(obj.type.IsByRef) //LDFLD to the structure accepts this structure address { if(! field.DeclaringType.Equals(obj.type.GetElementType()) || !field.DeclaringType.IsValueType ) throw new VerifierException(); } else TypeChecker.CheckAssignment(new TypeEx(field.DeclaringType),obj); } Type fieldType = field.FieldType; if(loadAddress) fieldType = TypeEx.BuildRefType(fieldType); stack.Push(fieldType); }
public static void ProcessBinOp(OpType opType, StackTypes stack) { switch(opType) { case OpType.Shift: { TypeEx shift = stack.Pop(); TypeEx t = stack.Pop(); if(!(TypeFixer.IsInt32OrCompatible(shift) || TypeFixer.IsIntPtrOrCompatible(shift))) throw new VerifierException(); if(!(TypeFixer.IsInt32OrCompatible(shift) || TypeFixer.IsIntPtrOrCompatible(shift) || TypeFixer.IsInt64OrCompatible(shift))) throw new VerifierException(); stack.Push(t); } break; case OpType.FloatOrInt: case OpType.Int: { TypeEx t1 = stack.Pop(); TypeEx t2 = stack.Pop(); TypeEx t3 = Arithmetics.GetReturnType(t1,t2,opType == OpType.FloatOrInt); stack.Push(t3); } break; case OpType.Compare: { TypeEx t1 = stack.Pop(); TypeEx t2 = stack.Pop(); Arithmetics.CheckTypes(t1,t2); stack.Push(typeof(int)); } break; } }
static public void ProcessLdObj(StackTypes stack, Type t) { TypeEx addr = stack.Pop(); if(!addr.type.IsByRef) throw new VerifierException(); if(!t.IsValueType) throw new VerifierException(); if(!t.Equals(addr.type.GetElementType())) throw new VerifierException(); stack.Push(t); }