예제 #1
0
        /// <summary>
        /// Accepts a field in the form "assemblyname#typename#fieldname" and returns the actual field
        /// </summary>
        /// <param name="Field"></param>
        /// <returns></returns>
        public static bool TryGetFieldFromPersistentStringForm(IPexComponent host, string fstr, out Field field)
        {
            field = null;

            var splitarr = fstr.Split(new char[] { PexMeConstants.PexMePersistenceFormSeparator });

            SafeDebug.Assume(splitarr.Length == 3, "Incorrect persistent store field name");

            var assemblyname = splitarr[0];
            var typename     = splitarr[1];
            var signature    = splitarr[2];

            FieldDefinition fdef;

            if (!TryGetFieldDefinition(host, assemblyname, typename, signature, out fdef))
            {
                return(false);
            }

            TypeDefinition tdef;

            if (!fdef.TryGetDeclaringType(out tdef))
            {
                return(false);
            }

            field = fdef.Instantiate(GetGenericTypeParameters(host, tdef));
            return(true);
        }
예제 #2
0
        public static string GeneratePUTCommand(Method putmethod)
        {
            TypeEx classdef;
            bool   bresult = putmethod.TryGetDeclaringType(out classdef);

            SafeDebug.Assume(bresult, "Declaring type cannot be null");

            var assemblyEx   = classdef.Definition.Module.Assembly;
            var assemblyName = assemblyEx.Location;
            var namespacestr = classdef.Namespace;

            StringBuilder sb = new StringBuilder();

            sb.Append("pex.exe ");
            sb.Append(assemblyName);
            sb.Append(" /nf:");
            sb.Append(namespacestr);
            sb.Append(" /tf:");
            sb.Append(classdef.ShortName.ToString() + "!");
            sb.Append(" /mf:");
            sb.Append(putmethod.ShortName.ToString() + "!");
            sb.Append(" /nor");
            sb.Append(" /rn:");
            sb.Append(classdef.ShortName.ToString() + "_" + putmethod.ShortName.ToString());
            if (PexMeConstants.ENABLE_DEBUGGING_MODE)
            {
                sb.Append(" /bos");
            }
            sb.Append(" /fullmscorlib");
            return(sb.ToString());
        }
예제 #3
0
 /// <summary>
 /// Gets a value indicating if the bitness is supported
 /// </summary>
 /// <param name="bitness">The bitness.</param>
 /// <returns>True if supported.</returns>
 public override bool SupportsProjectBitness(Bitness bitness)
 {
     SafeDebug.Assume(bitness != Bitness.Unsupported, "bitness != Bitness.Unsupported");
     if (Net2process)
     {
         return(bitness == Bitness.AnyCpu || bitness == Bitness.x86);
     }
     else
     {
         return(true);
     }
 }
예제 #4
0
        GetPersistentFieldDictionary(SafeDictionary <Field, FieldStore> fielddic)
        {
            var pfielddic = new System.Collections.Generic.Dictionary <string, PersistentFieldStore>();

            foreach (var field in fielddic.Keys)
            {
                var fieldstr = MethodOrFieldAnalyzer.GetPersistentStringFormOfField(field);
                PersistentFieldStore pfs;
                bool bresult = PersistentFieldStore.TryGetPersistentFieldStore(this.host, fielddic[field], out pfs);
                SafeDebug.Assume(bresult, "Failed to get persistent field store!!!");
                pfielddic[fieldstr] = pfs;
            }
            return(pfielddic);
        }
예제 #5
0
        public MethodEffects(IFiniteSet <Field> writtenInstanceFields,
                             IFiniteSet <Field> directSetFields, IFiniteSet <Method> directCalledMethods, IFiniteSet <Field> returnFields,
                             SafeDictionary <Field, FieldModificationType> modificationTypeDic,
                             int callDepth)
        {
            SafeDebug.AssumeNotNull(writtenInstanceFields, "writtenInstanceFields");
            SafeDebug.Assume(callDepth >= 0, "callDepth>=0");

            this.WrittenInstanceFields      = writtenInstanceFields;
            this.DirectSetterFields         = directSetFields;
            this.DirectCalledMethods        = directCalledMethods;
            this.ReturnFields               = returnFields;
            this.ModificationTypeDictionary = modificationTypeDic;
            this.CallDepth = callDepth;
        }
예제 #6
0
        GetPersistentMethodDictionary(SafeDictionary <Method, MethodStore> methoddic)
        {
            var pmethoddic = new System.Collections.Generic.Dictionary <string, PersistentMethodStore>();

            foreach (var method in methoddic.Keys)
            {
                var methodstr = MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(method);
                PersistentMethodStore pms;
                bool bresult = PersistentMethodStore.TryGetPersistentMethodStore(methoddic[method], out pms);
                SafeDebug.Assume(bresult, "Failed to get persistent method store!!!");
                pmethoddic[methodstr] = pms;
            }

            return(pmethoddic);
        }
        /// <summary>
        /// Function the retrieves associated Persistent store for each MethodStore
        /// </summary>
        /// <param name="ms"></param>
        /// <param name="pms"></param>
        /// <returns></returns>
        public static bool TryGetPersistentFieldStore(IPexComponent host, FieldStore fs, out PersistentFieldStore pfs)
        {
            pfs = new PersistentFieldStore();

            pfs.FieldName = MethodOrFieldAnalyzer.GetPersistentStringFormOfField(fs.FieldName);
            //foreach(var value in fs.FieldValues)
            //    pfs.FieldValues.Add(value);

            //TODO: Performance can be improved via caching over here
            foreach (var m in fs.ReadMethods)
            {
                pfs.ReadMethods.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(m));
            }

            foreach (var typeex in fs.WriteMethods.Keys)
            {
                HashSet <string> wmethods = new HashSet <string>();
                pfs.WriteMethods.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfTypeEx(typeex), wmethods);

                SafeSet <Method> methods;
                bool             bresult = fs.WriteMethods.TryGetValue(typeex, out methods);
                SafeDebug.Assume(bresult, "Failed to get associated set of methods for a type");

                var assemblyname = typeex.Definition.Module.Assembly.Location;
                var typename     = typeex.FullName;

                foreach (var m in methods)
                {
                    wmethods.Add(assemblyname + PexMeConstants.PexMePersistenceFormSeparator
                                 + typename + PexMeConstants.PexMePersistenceFormSeparator + MethodOrFieldAnalyzer.GetMethodSignature(m));
                }
            }

            foreach (var m in fs.ModificationTypeDictionary.Keys)
            {
                var value = fs.ModificationTypeDictionary[m];
                pfs.ModificationTypeDictionary.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(m), value);
            }

            foreach (var m in fs.PreciseModificationTypeDictionary.Keys)
            {
                var value = fs.PreciseModificationTypeDictionary[m];
                pfs.PreciseModificationTypeDictionary.Add(MethodOrFieldAnalyzer.GetPersistentStringFormOfMethod(m), value);
            }

            return(true);
        }
        internal SafeSet <Method> FilterCallingMethodsBasedOnField(Method tmw, Field field,
                                                                   SafeSet <Method> callingMethods)
        {
            SafeSet <Method> filteredMethods = new SafeSet <Method>();

            foreach (var callingm in callingMethods)
            {
                //Filter the calling method based on the field
                MethodBodyEx body;
                if (!callingm.TryGetBody(out body) || !body.HasInstructions)
                {
                    continue;
                }

                int         offset = 0;
                Instruction instruction;
                bool        bContinueWithNextMethod = false;
                Field       lastAccessedField       = null;
                while (body.TryGetInstruction(offset, out instruction) && !bContinueWithNextMethod)
                {
                    SafeDebug.AssumeNotNull(instruction, "instruction");
                    OpCode opCode = instruction.OpCode;
                    if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldflda)
                    {
                        SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField");
                        lastAccessedField = instruction.Field;
                    }
                    else if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt)
                    {
                        SafeDebug.Assume(opCode.OperandType == OperandType.InlineMethod, "opCode.OperandType == OperandType.InlineMethod");
                        Method methodinner = instruction.Method;

                        if (methodinner == tmw && field == lastAccessedField)
                        {
                            filteredMethods.Add(callingm);
                            bContinueWithNextMethod = true;
                        }
                        lastAccessedField = null;
                    }
                    offset = instruction.NextOffset;
                }
            }
            return(filteredMethods);
        }
예제 #9
0
        private static SafeDictionary <Field, FieldStore> GetFieldDictionary(IPexComponent host,
                                                                             System.Collections.Generic.Dictionary <string, PersistentFieldStore> pfielddic)
        {
            var fielddic = new SafeDictionary <Field, FieldStore>();

            foreach (var fieldstr in pfielddic.Keys)
            {
                Field field;
                bool  bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, fieldstr, out field);
                SafeDebug.Assume(bresult, "Failed to get field from persistent store!!!");

                FieldStore fs;
                bresult = PersistentFieldStore.TryGetFieldStore(host, pfielddic[fieldstr], out fs);
                SafeDebug.Assume(bresult, "Failed to get field store!!!");

                fielddic[field] = fs;
            }
            return(fielddic);
        }
예제 #10
0
        /// <summary>
        /// Returns a method call for a PUT. This should be of certain characteristics,
        /// It should contain only one method call as generated by us
        /// </summary>
        /// <param name="putmethod"></param>
        /// <returns></returns>
        public static bool TryRetrieveMethodCall(Method putmethod, out Method assocmethod)
        {
            SafeDebug.AssumeNotNull(putmethod, "putmethod");
            assocmethod = null;

            MethodBodyEx mbodyex;
            bool         bresult = putmethod.TryGetBody(out mbodyex);

            SafeDebug.Assert(bresult, "Failed to get the body");

            int         offset = 0;
            Instruction instruction;

            List <Method> allCalledMethods = new List <Method>();

            while (mbodyex.TryGetInstruction(offset, out instruction))
            {
                SafeDebug.AssumeNotNull(instruction, "instruction");
                OpCode opCode = instruction.OpCode;

                if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt)
                {
                    SafeDebug.Assume(opCode.OperandType == OperandType.InlineMethod,
                                     "opCode.OperandType == OperandType.InlineMethod");
                    allCalledMethods.Add(instruction.Method);
                }

                offset = instruction.NextOffset;
            }

            if (allCalledMethods.Count != 1)
            {
                return(false);
            }

            assocmethod = allCalledMethods[0];
            return(true);
        }
예제 #11
0
        /// <summary>
        /// Accepts a type in the form "assemblyname#typename" and returns the type name
        /// </summary>
        /// <param name="Field"></param>
        /// <returns></returns>
        public static bool TryGetTypeExFromPersistentStringForm(IPexComponent host, string typename, out TypeEx typeEx)
        {
            typeEx = null;

            var splitarr = typename.Split(new char[] { PexMeConstants.PexMePersistenceFormSeparator });

            SafeDebug.Assume(splitarr.Length == 2, "Incorrect persistent store type name");

            try
            {
                bool result = TryGetTypeExFromName(host, splitarr[0], splitarr[1], out typeEx);
                if (typeEx == null || !result)
                {
                    return(false);
                }

                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }
예제 #12
0
        /// <summary>
        /// Computes method effects statically. All written fields of a method.
        /// Can be imprecise and conservative
        /// </summary>
        /// <param name="declaringType"></param>
        /// <param name="method"></param>
        /// <param name="effects"></param>
        /// <returns></returns>
        public static bool TryComputeMethodEffects(IPexComponent host, TypeEx declaringType, Method method,
                                                   SafeSet <Method> visitedMethods, out MethodEffects effects)
        {
            SafeDebug.AssumeNotNull(declaringType, "declaringType");
            SafeDebug.AssumeNotNull(method, "method");

            try
            {
                if (visitedMethods == null)
                {
                    visitedMethods = new SafeSet <Method>();
                }

                if (visitedMethods.Contains(method))
                {
                    effects = null;
                    return(false);
                }

                visitedMethods.Add(method);

                //Check whether this has been computed before
                var psd = host.GetService <IPexMeStaticDatabase>() as PexMeStaticDatabase;
                if (psd.MethodEffectsDic.TryGetValue(method.GlobalIndex, out effects))
                {
                    return(true);
                }

                var res                 = new SafeSet <string>();
                var directSetFields     = new SafeSet <string>();
                var directCalledMethods = new SafeSet <Method>();
                var returnFields        = new SafeSet <Field>();
                var modificationTypeDic = new SafeDictionary <string, FieldModificationType>();
                var parameters          = method.Parameters;

                MethodBodyEx body;
                if (!method.TryGetBody(out body) || !body.HasInstructions)
                {
                    effects = null;
                    return(false);
                }

                int         callDepth = 0;
                int         offset    = 0;
                Instruction instruction;
                OpCode      prevOpcode = OpCodes.Nop;

                //Stack for load instructions
                Field lastAccessedArrayField = null;
                Field lastAccessedField      = null;

                while (body.TryGetInstruction(offset, out instruction))
                {
                    SafeDebug.AssumeNotNull(instruction, "instruction");
                    OpCode opCode = instruction.OpCode;
                    if (LdcOpCodes.Contains(opCode))
                    {
                        //topIsConstant = true;
                    }
                    else if (ConvOpCodes.Contains(opCode))
                    {
                        // do not change topIsConstant
                    }
                    else
                    {
                        if (opCode == OpCodes.Stfld)
                        {
                            SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField");
                            Field field = instruction.Field;
                            AddFieldToMethodEffects(host, declaringType, res, directSetFields, modificationTypeDic, prevOpcode, field, field.Type);
                        }
                        else if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldflda)
                        {
                            SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField");
                            Field accessedField = instruction.Field;

                            if (accessedField.Type.Spec == TypeSpec.SzArray)
                            {
                                lastAccessedArrayField = accessedField;
                            }
                            else
                            {
                                lastAccessedField = accessedField;
                            }
                        }
                        else if (StElemOpCodes.Contains(opCode))
                        {
                            if (lastAccessedArrayField != null)
                            {
                                //Indicates that there is n array type modified
                                AddFieldToMethodEffects(host, declaringType, res, directSetFields, modificationTypeDic, prevOpcode, lastAccessedArrayField, lastAccessedArrayField.Type);
                                lastAccessedArrayField = null;
                            }
                        }
                        else if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt)
                        {
                            SafeDebug.Assume(opCode.OperandType == OperandType.InlineMethod, "opCode.OperandType == OperandType.InlineMethod");
                            Method methodinner = instruction.Method;
                            SafeDebug.AssumeNotNull(method, "method");

                            directCalledMethods.Add(methodinner);
                            TypeEx methodDeclaringType;

                            //are these function calls are within the parent types
                            if (methodinner.TryGetDeclaringType(out methodDeclaringType) &&
                                declaringType.IsAssignableTo(methodDeclaringType))
                            {
                                MethodEffects methodEffects;
                                if (TryComputeMethodEffects(host, methodDeclaringType, methodinner, visitedMethods, out methodEffects))
                                {
                                    res.AddRange(methodEffects.WrittenInstanceFields);
                                    foreach (var key in methodEffects.ModificationTypeDictionary.Keys)
                                    {
                                        modificationTypeDic[key] = methodEffects.ModificationTypeDictionary[key];
                                    }
                                    directSetFields.AddRange(methodEffects.DirectSetterFields);
                                    if (methodEffects.CallDepth > callDepth)
                                    {
                                        callDepth = methodEffects.CallDepth;
                                    }
                                }
                            }
                            else
                            {
                                //introducing heuristics for inter-procedural static analysis
                                if (lastAccessedField != null && lastAccessedField.Type.IsReferenceType &&
                                    !(methodinner.ShortName.StartsWith("Get") || methodinner.ShortName.StartsWith("get") ||
                                      methodinner.ShortName.StartsWith("Set") || methodinner.ShortName.StartsWith("set")))
                                {
                                    AddFieldToMethodEffects(host, declaringType, res, directSetFields, modificationTypeDic,
                                                            prevOpcode, lastAccessedField, lastAccessedField.Type);
                                }
                            }
                        }
                        else if (opCode == OpCodes.Ret)
                        {
                            if (instruction.Field != null)
                            {
                                returnFields.Add(instruction.Field);
                            }
                        }
                        //topIsConstant = false;
                    }

                    prevOpcode = opCode;
                    offset     = instruction.NextOffset;
                }

                effects = new MethodEffects((IFiniteSet <string>)res, directSetFields, directCalledMethods, returnFields, modificationTypeDic, callDepth + 1);
                psd.MethodEffectsDic[method.GlobalIndex] = effects;
                return(true);
            }
            catch (Exception ex)
            {
                host.Log.LogErrorFromException(ex, WikiTopics.MissingWikiTopic, "methodeffects",
                                               "Failed to compute method effects for method " + method.FullName + "," + ex.Message);
                effects = null;
                return(false);
            }
        }
예제 #13
0
        public static TypeEx AddFieldToMethodEffects(IPexComponent host, TypeEx declaringType, SafeSet <string> res,
                                                     SafeSet <string> directSetFields, SafeDictionary <string, FieldModificationType> modificationTypeDic,
                                                     OpCode prevOpcode, Field field, TypeEx fieldType)
        {
            SafeDebug.AssumeNotNull(field, "field");
            SafeDebug.Assume(!field.IsStatic, "!field.IsStatic");

            TypeEx fieldDeclaringType;

            //The following check ensures that the field belongs to this class
            //or its base classes
            if (field.TryGetDeclaringType(out fieldDeclaringType) &&
                declaringType.IsAssignableTo(fieldDeclaringType))
            {
                res.Add(field.ShortName);

                FieldModificationType fmt = FieldModificationType.UNKNOWN;
                if (fieldType == SystemTypes.Int32 || fieldType == SystemTypes.Int64 || fieldType == SystemTypes.Int16)
                {
                    if (prevOpcode == OpCodes.Add)
                    {
                        fmt = FieldModificationType.INCREMENT;
                    }
                    else if (prevOpcode == OpCodes.Sub)
                    {
                        fmt = FieldModificationType.DECREMENT;
                    }
                    else if (prevOpcode == OpCodes.Call || prevOpcode == OpCodes.Calli || prevOpcode == OpCodes.Callvirt)
                    {
                        fmt = FieldModificationType.METHOD_CALL;
                    }
                    else
                    {
                        host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype",
                                            "Encountered unknown modification type for integer type " + prevOpcode);
                    }
                }
                else
                {
                    if (field.Type.IsReferenceType)
                    {
                        if (prevOpcode == OpCodes.Ldnull)
                        {
                            fmt = FieldModificationType.NULL_SET;
                        }
                        else if (prevOpcode == OpCodes.Newarr || prevOpcode == OpCodes.Newobj)
                        {
                            fmt = FieldModificationType.NON_NULL_SET;
                        }
                        else if (LdArgOpCodes.Contains(prevOpcode))
                        {
                            fmt = FieldModificationType.NON_NULL_SET;
                        }
                        else
                        {
                            fmt = FieldModificationType.METHOD_CALL;    //A method call is invoked on this field, which updates this field
                        }
                    }
                    else if (fieldType == SystemTypes.Bool)
                    {
                        if (prevOpcode == OpCodes.Ldc_I4_0)
                        {
                            fmt = FieldModificationType.FALSE_SET;
                        }
                        else if (prevOpcode == OpCodes.Ldc_I4_1)
                        {
                            fmt = FieldModificationType.TRUE_SET;
                        }
                        else
                        {
                            host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype",
                                                "Encountered unknown modification type for boolean type " + prevOpcode);
                        }
                    }
                }

                //Store the value of fmt. Sometimes, the same field
                //can be modified in different ways within the method, for example
                //setting a boolean field to both true or false. In that case, the modification
                //type is left as unknown
                FieldModificationType prevFMT;
                if (modificationTypeDic.TryGetValue(field.ShortName, out prevFMT))
                {
                    //There is some entry for this field
                    if (prevFMT != FieldModificationType.UNKNOWN && prevFMT != fmt)
                    {
                        modificationTypeDic[field.ShortName] = FieldModificationType.UNKNOWN;
                    }
                }
                else
                {
                    modificationTypeDic[field.ShortName] = fmt;
                }


                //A heuristic based approach for aliasing analysis for checking whether the field is directly
                //assigned any parameters
                if (LdArgOpCodes.Contains(prevOpcode))
                {
                    directSetFields.Add(field.ShortName);
                }
            }
            return(fieldDeclaringType);
        }
        /// <summary>
        /// Function that retrieves associated method store
        /// </summary>
        /// <param name="pms"></param>
        /// <param name="ms"></param>
        /// <returns></returns>
        public static bool TryGetFieldStore(IPexComponent host, PersistentFieldStore pfs, out FieldStore fs)
        {
            fs = new FieldStore();

            bool bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, pfs.FieldName, out fs.FieldName);

            SafeDebug.Assume(bresult, "Failed to get field from the persistent store");

            fs.FieldValues.AddRange(pfs.FieldValues);

            //TODO: Performance can be improved via caching over here
            foreach (var mname in pfs.ReadMethods)
            {
                Method m;
                bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, mname, out m);
                SafeDebug.Assume(bresult, "Failed to get method from persistent string form ");
                fs.ReadMethods.Add(m);
            }

            foreach (var typeex in pfs.WriteMethods.Keys)
            {
                SafeSet <Method> wmethods = new SafeSet <Method>();
                TypeEx           typeEx;
                bresult = MethodOrFieldAnalyzer.TryGetTypeExFromPersistentStringForm(host, typeex, out typeEx);
                SafeDebug.Assume(bresult, "Failed to get type from persistent string form " + typeex);

                fs.WriteMethods.Add(typeEx, wmethods);

                HashSet <string> methods;
                bresult = pfs.WriteMethods.TryGetValue(typeex, out methods);
                SafeDebug.Assume(bresult, "Failed to get associated set of methods for a type " + typeex);

                foreach (var m in methods)
                {
                    Method method;
                    bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method);
                    SafeDebug.Assume(bresult, "Failed to get method from string form " + m);
                    wmethods.Add(method);
                }
            }

            foreach (var m in pfs.ModificationTypeDictionary.Keys)
            {
                var    value = pfs.ModificationTypeDictionary[m];
                Method method;
                bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method);
                SafeDebug.Assume(bresult, "Failed to get method from string form " + m);
                fs.ModificationTypeDictionary.Add(method, value);
            }

            foreach (var m in pfs.PreciseModificationTypeDictionary.Keys)
            {
                var    value = pfs.PreciseModificationTypeDictionary[m];
                Method method;
                bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method);
                SafeDebug.Assume(bresult, "Failed to get method from string form " + m);
                fs.PreciseModificationTypeDictionary.Add(method, value);
            }

            return(true);
        }
예제 #15
0
 /// <summary>
 /// The supports project bitness.
 /// </summary>
 /// <param name="bitness">
 /// The bitness.
 /// </param>
 /// <returns>
 /// The <see cref="bool"/>.
 /// </returns>
 public override bool SupportsProjectBitness(Bitness bitness)
 {
     SafeDebug.Assume(bitness != Bitness.Unsupported, "bitness != Bitness.Unsupported");
     return(true);
 }
예제 #16
0
        /// <summary>
        /// Retrieves the PUT for the method we are looking for in the current assembly
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public static bool TryRetrievePUT(IPexComponent host, AssemblyEx assembly, Method method, out Method putmethod)
        {
            //Get the class name of the target class that is including
            //the method we are looking for
            TypeEx declaringType;
            bool   bresult = method.TryGetDeclaringType(out declaringType);

            SafeDebug.Assume(bresult, "Failed to get the declaring type!!!");

            string tclassname       = null;
            var    declaringTypeDef = declaringType.Definition;

            if (declaringTypeDef.GenericTypeParametersCount == 0)
            {
                tclassname = declaringType.ShortName.ToString();
            }
            else
            {
                tclassname = declaringType.ShortName.ToString();
                tclassname = tclassname.Substring(0, tclassname.IndexOf('`'));

                foreach (var param in declaringTypeDef.GenericTypeParameters)
                {
                    tclassname = tclassname + param.Name;
                }
            }
            tclassname = tclassname + "Test";

            foreach (var classdef in assembly.TypeDefinitions)
            {
                if (classdef.ShortName != tclassname)
                {
                    continue;
                }

                //TODO: To be more robust, we can later replace
                //this piece of code by actually checking whether there
                //is a method call to the method of the library we are looking for
                foreach (var mdef in classdef.DeclaredInstanceMethods)
                {
                    if (mdef.ShortName == method.ShortName)
                    {
                        bool isPexMethod = false;
                        foreach (var attr in mdef.DeclaredAttributes)
                        {
                            if (attr.SerializableName.ToString().Contains("PexMethodAttribute"))
                            {
                                isPexMethod = true;
                                break;
                            }
                        }

                        if (isPexMethod)
                        {
                            putmethod = mdef.Instantiate(MethodOrFieldAnalyzer.GetGenericTypeParameters(host, classdef),
                                                         MethodOrFieldAnalyzer.GetGenericMethodParameters(host, mdef));
                            return(true);
                        }
                    }
                }
            }

            putmethod = null;
            return(false);
        }
        // Find out how many fields require user provided factory methods
        public static bool GetTargetExplorableField(IEnumerable <Field> involvedFields, out Field targetField,
                                                    out TypeEx declaringType, IPexComponent host, out TypeEx targetType)
        {
            targetField = null;
            var allInvolvedFields = new SafeList <Field>();

            allInvolvedFields.AddRange(involvedFields);
            int numFields = allInvolvedFields.Count;

            if (numFields < 1)
            {
                declaringType = null;
                targetType    = null;
                return(false);
            }
//
//            if (numFields == 1)
//            {
//                targetField = allInvolvedFields[0];
//                if (!MethodOrFieldAnalyzer.TryGetDeclaringTypeDefinition(host, targetField, out declaringType))
//                {
//                    declaringType = null;
//                    return false;
//                }
//                return true;
//            }

//            allInvolvedFields.Reverse();
            TypeEx prevFieldType = null;

            for (int count = 0; count < allInvolvedFields.Count; count++)
            {
                var currentField = allInvolvedFields[count];
//                if (count + 1 < allInvolvedFields.Count)
//                {
//                    prevFieldType = allInvolvedFields[count + 1].Type;
//                }

                if (!MethodOrFieldAnalyzer.TryGetDeclaringTypeDefinition(host, currentField, out declaringType))
                {
                    host.Log.LogError(WikiTopics.MissingWikiTopic, "targetfield",
                                      "Failed to get the declaring type for the field " + currentField.FullName);
                    ErrorLog.AppendLine("Failed to get the declaring type for the field " + currentField.FullName);
                    targetType = null;
                    return(false);
                }

                try
                {
                    SafeDebug.Assume(
                        prevFieldType == null || prevFieldType == declaringType ||
                        prevFieldType.IsAssignableTo(declaringType) ||
                        declaringType.IsAssignableTo(prevFieldType),
                        "The current field type (" + declaringType + ") should be the same as the previous field type (" +
                        prevFieldType + ")");


                    if (MethodOrFieldAnalyzer.IsFieldExternallyVisible(host, declaringType, currentField))
                    {
                        prevFieldType = currentField.Type;
                        continue;
                    }
                }
                catch (Exception ex)
                {
                    ErrorLog.AppendLine("Failed to compute external visibility of field " + currentField.FullName + " because of " + ex);
                }

                targetField = currentField;
                targetType  = declaringType;
                return(true);
            }

            targetField = allInvolvedFields[allInvolvedFields.Count - 1];
            if (!MethodOrFieldAnalyzer.TryGetDeclaringTypeDefinition(host, targetField, out declaringType))
            {
                host.Log.LogError(WikiTopics.MissingWikiTopic, "targetfield",
                                  "Failed to get the declaring type for the field " + targetField.FullName);
                targetType = null;
                return(false);
            }
            targetType = targetField.Type;
            return(true);
        }
예제 #18
0
        /// <summary>
        /// Function that retrieves associated method store
        /// </summary>
        /// <param name="pms"></param>
        /// <param name="ms"></param>
        /// <returns></returns>
        public static bool TryGetMethodStore(IPexComponent host, PersistentMethodStore pms, out MethodStore ms)
        {
            ms = new MethodStore();

            bool bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, pms.methodName, out ms.methodName);

            SafeDebug.Assume(bresult, "Failed to get the method from persistent form " + pms.methodName);

            foreach (var fieldstr in pms.ReadFields)
            {
                Field field;
                bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, fieldstr, out field);
                SafeDebug.Assume(bresult, "Failed to get the field from persistent form " + fieldstr);
                ms.ReadFields.Add(field);
            }

            foreach (var fieldstr in pms.WriteFields)
            {
                Field field;
                bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, fieldstr, out field);
                SafeDebug.Assume(bresult, "Failed to get the field from persistent form " + fieldstr);
                ms.WriteFields.Add(field);
            }

            foreach (var typeexstr in pms.CallingMethods.Keys)
            {
                SafeSet <Method> wmethods = new SafeSet <Method>();
                TypeEx           typeEx;
                bresult = MethodOrFieldAnalyzer.TryGetTypeExFromPersistentStringForm(host, typeexstr, out typeEx);
                if (!bresult)
                {
                    //No strict safedebugging cannot be added for calling methods since there
                    //can be several dummy methods from Pex side
                    continue;
                }

                ms.CallingMethods.Add(typeEx, wmethods);

                var methods = pms.CallingMethods[typeexstr];
                foreach (var mstr in methods)
                {
                    Method method;
                    bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, mstr, out method);
                    if (!bresult)
                    {
                        continue;
                    }
                    wmethods.Add(method);
                }
            }

            foreach (var calledMethodStr in pms.CalledMethods)
            {
                Method method;
                bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, calledMethodStr, out method);
                if (!bresult)
                {
                    continue;
                }
                ms.CalledMethods.Add(method);
            }

            return(true);
        }
예제 #19
0
        /// <summary>
        /// Collects defs and uses within a method
        /// </summary>
        /// <param name="td"></param>
        /// <param name="ade"></param>
        /// <param name="constructor"></param>
        private static void CollectDefsAndUsesInMethod(PexMeStaticDatabase psd, TypeDefinition td, DeclClassEntity ade,
                                                       Method method, SafeSet <Method> visitedMethods, SideEffectStore ses)
        {
            try
            {
                if (visitedMethods == null)
                {
                    visitedMethods = new SafeSet <Method>();
                }

                if (visitedMethods.Contains(method))
                {
                    return;
                }
                visitedMethods.Add(method);

                MethodBodyEx body;
                if (!method.TryGetBody(out body) || !body.HasInstructions)
                {
                    return;
                }

                int         offset = 0;
                Instruction instruction;
                OpCode      prevOpcode = OpCodes.Nop;

                //Stack for load instructions
                Field            lastAccessedArrayField = null;
                SafeList <Field> lastAccessedFieldList  = new SafeList <Field>();

                while (body.TryGetInstruction(offset, out instruction))
                {
                    SafeDebug.AssumeNotNull(instruction, "instruction");
                    OpCode opCode = instruction.OpCode;
                    if (MethodOrFieldAnalyzer.LdcOpCodes.Contains(opCode))
                    {
                        //topIsConstant = true;
                    }
                    else if (MethodOrFieldAnalyzer.ConvOpCodes.Contains(opCode))
                    {
                        // do not change topIsConstant
                    }
                    else
                    {
                        if (opCode == OpCodes.Stfld)
                        {
                            SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField");
                            Field           field = instruction.Field;
                            DeclFieldEntity dfe;
                            if (ade.FieldEntities.TryGetValue(field.FullName, out dfe))
                            {
                                //Found a definition of the field. register the definition
                                dfe.AddToDefList(method, offset);
                            }
                        }
                        else if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldflda)
                        {
                            SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField");
                            Field accessedField = instruction.Field;
                            if (PexMeFilter.IsPrimitiveType(accessedField.Type))
                            {
                                DeclFieldEntity dfe;
                                if (ade.FieldEntities.TryGetValue(accessedField.FullName, out dfe))
                                {
                                    //Found an accessor. register the usage
                                    dfe.AddToUseList(method, offset);
                                }
                                lastAccessedArrayField = null;
                            }
                            else
                            {
                                if (accessedField.Type.Spec == TypeSpec.SzArray)
                                {
                                    lastAccessedArrayField = accessedField;
                                }
                                else
                                {
                                    //Any access needs to be registered as use
                                    lastAccessedFieldList.Add(accessedField);
                                }
                            }
                        }
                        else if (MethodOrFieldAnalyzer.StElemOpCodes.Contains(opCode))
                        {
                            if (lastAccessedArrayField != null)
                            {
                                DeclFieldEntity dfe;
                                if (ade.FieldEntities.TryGetValue(lastAccessedArrayField.FullName, out dfe))
                                {
                                    //Found a definition of the field. register the definition
                                    dfe.AddToDefList(method, offset);
                                }
                                lastAccessedArrayField = null;
                            }
                        }
                        else if (MethodOrFieldAnalyzer.BranchOpCodes.Contains(opCode))
                        {
                            if (lastAccessedFieldList.Count > 0)
                            {
                                //A field is loaded and used in conditional statement. We use the offset of conditional statement as the usage point
                                foreach (var field in lastAccessedFieldList)
                                {
                                    DeclFieldEntity dfe;
                                    if (ade.FieldEntities.TryGetValue(field.FullName, out dfe))
                                    {
                                        //Found a definition of the field. register the definition
                                        dfe.AddToUseList(method, offset);
                                    }
                                }
                                lastAccessedFieldList.Clear();
                            }

                            if (lastAccessedArrayField != null)
                            {
                                DeclFieldEntity dfe;
                                if (ade.FieldEntities.TryGetValue(lastAccessedArrayField.FullName, out dfe))
                                {
                                    //Found a definition of the field. register the definition
                                    dfe.AddToUseList(method, offset);
                                }
                                lastAccessedArrayField = null;
                            }
                        }
                        else if (opCode == OpCodes.Ret)
                        {
                            //A field is accessed and is returned from here
                            if (lastAccessedFieldList.Count > 0)
                            {
                                foreach (var field in lastAccessedFieldList)
                                {
                                    DeclFieldEntity dfe;
                                    if (ade.FieldEntities.TryGetValue(field.FullName, out dfe))
                                    {
                                        //Found a use of the field. register the definition
                                        dfe.AddToUseList(method, offset);
                                    }
                                }
                                lastAccessedFieldList.Clear();
                            }
                        }
                        else if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt)
                        {
                            SafeDebug.Assume(opCode.OperandType == OperandType.InlineMethod, "opCode.OperandType == OperandType.InlineMethod");
                            Method methodinner = instruction.Method;
                            SafeDebug.AssumeNotNull(method, "method");

                            //If this condition is not satisfied, it could be a local method call, which is dealt separately
                            if (lastAccessedFieldList.Count != 0)
                            {
                                HandleMethodCall(psd, ade, method, offset, lastAccessedFieldList, methodinner, ses);
                                lastAccessedFieldList.Clear();
                            }
                            else
                            {
                                var shortname = methodinner.ShortName;
                                if (shortname.StartsWith("set_"))
                                {
                                    HandleSetterMethod(ade, method, offset, methodinner);
                                }
                                else if (shortname.StartsWith("get_"))
                                {
                                    HandleGetterMethod(ade, method, offset, methodinner, lastAccessedFieldList);
                                }
                            }
                        }
                    }
                    prevOpcode = opCode;
                    offset     = instruction.NextOffset;
                }
            }
            catch (Exception ex)
            {
                logger.ErrorException("Exception thrown with static analysis " + ex.StackTrace, ex);
            }
        }
예제 #20
0
        private static TypeEx AddFieldToMethodEffects(IPexComponent host, TypeEx declaringType, SafeSet <Field> res,
                                                      SafeSet <Field> directSetFields,
                                                      SafeDictionary <Field, FieldModificationType> modificationTypeDic,
                                                      OpCode prevOpcode, Field field, TypeEx fieldType)
        {
            SafeDebug.AssumeNotNull(field, "field");
            SafeDebug.Assume(!field.IsStatic, "!field.IsStatic");

            TypeEx fieldDeclaringType;

            //The following check ensures that the field belongs to this class
            //or its base classes
            if (field.TryGetDeclaringType(out fieldDeclaringType) &&
                declaringType.IsAssignableTo(fieldDeclaringType))
            {
                res.Add(field);

                var fieldTypeStr = fieldType.ToString();
                if (fieldTypeStr == "System.Int32" || fieldTypeStr == "System.Int64" || fieldTypeStr == "System.Int16")
                {
                    if (prevOpcode == OpCodes.Add)
                    {
                        modificationTypeDic[field] = FieldModificationType.INCREMENT;
                    }
                    else if (prevOpcode == OpCodes.Sub)
                    {
                        modificationTypeDic[field] = FieldModificationType.DECREMENT;
                    }
                    else
                    {
                        host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype",
                                            "Encountered unknown modification type for integer type " + prevOpcode);
                    }
                }
                else
                {
                    if (field.Type.IsReferenceType)
                    {
                        if (prevOpcode == OpCodes.Ldnull)
                        {
                            modificationTypeDic[field] = FieldModificationType.NULL_SET;
                        }
                        else if (prevOpcode == OpCodes.Newarr || prevOpcode == OpCodes.Newobj)
                        {
                            modificationTypeDic[field] = FieldModificationType.NON_NULL_SET;
                        }
                        else
                        {
                            host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype",
                                                "Encountered unknown modification type for reference type " + prevOpcode);
                        }
                    }
                    else if (fieldTypeStr == "System.Boolean")
                    {
                        if (prevOpcode == OpCodes.Ldc_I4_0)
                        {
                            modificationTypeDic[field] = FieldModificationType.FALSE_SET;
                        }
                        else if (prevOpcode == OpCodes.Ldc_I4_1)
                        {
                            modificationTypeDic[field] = FieldModificationType.TRUE_SET;
                        }
                        else
                        {
                            host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype",
                                                "Encountered unknown modification type for boolean type " + prevOpcode);
                        }
                    }
                }

                //A heuristic based approach for aliasing analysis for checking whether the field is directly
                //assigned any parameters
                if (LdArgOpCodes.Contains(prevOpcode))
                {
                    directSetFields.Add(field);
                }
            }
            return(fieldDeclaringType);
        }