Exemple #1
0
        private static string GetModificationTypeStr(FieldModificationType fmt)
        {
            switch (fmt)
            {
            case FieldModificationType.DECREMENT: return("DECREMENT");

            case FieldModificationType.INCREMENT: return("INCREMENT");

            case FieldModificationType.INCREMENT_ONE: return("INCREMENT_ONE");

            case FieldModificationType.NULL_SET: return("NULL_SET");

            case FieldModificationType.NON_NULL_SET: return("NON_NULL_SET");

            case FieldModificationType.UNKNOWN: return("UNKNOWN");

            case FieldModificationType.TRUE_SET: return("TRUE_SET");

            case FieldModificationType.FALSE_SET: return("FALSE_SET");

            case FieldModificationType.METHOD_CALL: return("METHOD_CALL");

            default: return("UNKNOWN");
            }
        }
        /// <summary>
        /// Given a uncovered code location and the associated terms, this
        /// method infers factory method for that code location.
        ///
        /// Assumes that the uncovered branch is mainly due to an object creating issue
        /// </summary>
        /// <returns></returns>
        public bool TryInferFactoryMethod(UncoveredCodeLocationStore ucls, out SafeSet <Method> suggestedMethods)
        {
            SafeDebug.AssumeNotNull(ucls, "ucls");

            if (ucls.AllFields.Count == 0)
            {
                this.host.Log.LogError(WikiTopics.MissingWikiTopic, "factoryguesser",
                                       "No information about involving fields in the uncovered branch");
                suggestedMethods = null;
                return(false);
            }

            //Check whether the feature is currently supported
            FieldModificationType fmt = this.GetRequiredFieldModificationType(ucls);

            if (!(fmt == FieldModificationType.NON_NULL_SET ||
                  fmt == FieldModificationType.NULL_SET || fmt == FieldModificationType.INCREMENT || fmt == FieldModificationType.DECREMENT ||
                  fmt == FieldModificationType.FALSE_SET || fmt == FieldModificationType.TRUE_SET))
            {
                this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "factoryguesser",
                                         "Format " + fmt.ToString() + " is not supported for suggesting factory methods");
                suggestedMethods = null;
                return(false);
            }

            //Step 1: Get the exact type whose factory method is required for covering this branch.
            //Decided based on where there is a subsequent field which can be directly handled rather than the top field.
            //This step is moved to the place where the uncovered location is initially stored

            //Step 2: Decide which methods of this type should be invoked. Use a bottomup approach
            //for inferrinfg the exact method
            if (!this.GetTargetMethod(ucls, ucls.TargetField, out suggestedMethods))
            {
                this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "factoryguesser",
                                         "Failed to retrieve the target method of field " + ucls.TargetField.FullName + " in type " + ucls.ExplorableType.FullName);
                suggestedMethods = null;
                return(false);
            }

            var sb = new StringBuilder();

            foreach (var m in suggestedMethods)
            {
                sb.AppendLine(MethodOrFieldAnalyzer.GetMethodSignature(m));
            }
            ucls.SuggestedMethodsforFactory = sb.ToString();

            //Create a factory suggestion store. This is expected by the rest of the code.
            FactorySuggestionStore fss;

            if (!this.pmd.FactorySuggestionsDictionary.TryGetValue(ucls.ExplorableType.ToString(), out fss))
            {
                fss = new FactorySuggestionStore();
                fss.DeclaringType = ucls.ExplorableType.ToString();
                this.pmd.FactorySuggestionsDictionary[ucls.ExplorableType.ToString()] = fss;
            }

            return(true);
        }
        /// <summary>
        /// Includes filtering of the methods based on desired format
        /// </summary>
        /// <returns></returns>
        public bool TryGetFilteredWriteMethods(Field field, TypeEx declaringType, FieldModificationType desiredfmt, out SafeSet <Method> writeMethods)
        {
            //Check in the predefined store before proceeding
            if (PreDefinedMethodEffects.TryGetWriteMethods(this, field, desiredfmt, out writeMethods))
            {
                SafeSet <Method> newWriteMethods = new SafeSet <Method>();
                GetCallingMethods(field, declaringType, writeMethods, newWriteMethods);

                //Filter those methods whose actual types are abstract
                SafeSet <Method> returnMethods = new SafeSet <Method>();
                foreach (Method m in writeMethods)
                {
                    TypeEx declType;
                    if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface)
                    {
                        returnMethods.Add(m);
                    }
                }

                foreach (Method m in newWriteMethods)
                {
                    TypeEx declType;
                    if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface)
                    {
                        returnMethods.Add(m);
                    }
                }

                writeMethods.Clear();
                writeMethods.AddRange(returnMethods);
                return(true);
            }

            //Identify those method that directly modify this field
            if (!TryGetWriteMethods(field, declaringType, out writeMethods))
            {
                return(false);
            }

            //C# supports properties. In that case, the property setter can also
            //be a viable method. add property setter and its callers also
            Property property;

            if (MethodOrFieldAnalyzer.TryGetPropertyModifyingField(this, declaringType, field, out property))
            {
                if (property.IsVisible(VisibilityContext.Exported))
                {
                    writeMethods.Add(property.Setter);
                }

                var newWriteMethods = new SafeSet <Method>();
                GetCallingMethods(field, declaringType, writeMethods, newWriteMethods);
                writeMethods.AddRange(newWriteMethods);
            }

            writeMethods = FilterWriteMethodsOfUpdateType(field, desiredfmt, writeMethods);
            return(true);
        }
Exemple #4
0
        /// <summary>
        /// Gets textual form of modification type
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public static string GetPreciseModificationType(FieldStore fs, Method method)
        {
            if (!fs.PreciseModificationTypeDictionary.ContainsKey(method))
            {
                return("UNKNOWN");
            }

            FieldModificationType fmt = fs.PreciseModificationTypeDictionary[method];

            return(GetModificationTypeStr(fmt));
        }
Exemple #5
0
        /// <summary>
        /// Checks whether there are any looping requireements based on looping threshold and enhances
        /// the sequence accordingly. Applies only for INCREMENT and DECREMENT field modification types
        /// </summary>
        /// <param name="pucls"></param>
        /// <param name="p"></param>
        private void CheckNEnhanceForLooping(PersistentUncoveredLocationStore pucls,
                                             int fitnessval, FieldModificationType fmt, SafeList <Field> culpritFields)
        {
            if (fmt != FieldModificationType.INCREMENT && fmt != FieldModificationType.DECREMENT)
            {
                return;
            }

            //Not even a single execution happened on this location.
            if (fitnessval == Int32.MaxValue)
            {
                return;
            }

            var        field = culpritFields[0];
            FieldStore fs;

            if (!this.pmd.FieldDictionary.TryGetValue(field, out fs))
            {
                return;
            }

            Dictionary <string, Method> writeMethods = new Dictionary <string, Method>();

            foreach (var mset in fs.WriteMethods.Values)
            {
                foreach (var m in mset)
                {
                    var sig = MethodOrFieldAnalyzer.GetMethodSignature(m);
                    writeMethods.Add(sig, m);
                }
            }

            foreach (var seq in pucls.SuggestedMethodSequences)
            {
                string loop_method;
                if (!this.IsEligibleForLooping(seq, field, writeMethods, fs, out loop_method))
                {
                    continue;
                }

                pucls.LoopingFeatureApplied = true;
                this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "LoopingFeature",
                                         "Applying looping feature on method: " + loop_method + " (" + (fitnessval - 1) + ")");
                for (int count = 1; count < fitnessval; count++)
                {
                    seq.Sequence.Add(loop_method);
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Checks whether fitness strategy matters or not. Since, fitness
        /// is required only for integers, but not for all kinds of types such
        /// as boolean or non-null
        /// </summary>
        /// <returns></returns>
        private bool IsFitnessRequired(FieldModificationType fmt)
        {
            switch (fmt)
            {
            case FieldModificationType.INCREMENT:
            case FieldModificationType.DECREMENT:
            case FieldModificationType.INCREMENT_ONE:
                return(true);

            case FieldModificationType.FALSE_SET:
            case FieldModificationType.TRUE_SET:
            case FieldModificationType.NULL_SET:
            case FieldModificationType.NON_NULL_SET:
                return(false);

            default:
                return(false);
            }
        }
        /// <summary>
        /// Retrieves the write methods for a field, if exists from the predefined settings.
        /// </summary>
        public static bool TryGetWriteMethods(IPexComponent host, Field field, FieldModificationType desiredFmt, 
            out SafeSet<Method> writeMethods)
        {
            if (!isPredefinedEffectsParsed)
                ParsePredefinedEffects(host);

            PreDefinedMethodEffectsStore pdme = new PreDefinedMethodEffectsStore(field, desiredFmt);
            PreDefinedMethodEffectsStore existingPdme;
            if (effectsStore.TryGetValue(pdme, out existingPdme))
            {
                writeMethods = new SafeSet<Method>();
                writeMethods.AddRange(existingPdme.suggestedmethodList);
                return true;
            }
            else
            {
                writeMethods = null;
                return false;
            }
        }
        /// <summary>
        /// Given a set of write methods, this method basically filters them out
        /// to create a new set. Also filters the method that belongs to the interface type
        /// </summary>
        /// <param name="field"></param>
        /// <param name="fieldModificationType"></param>
        /// <param name="writeMethods"></param>
        /// <returns></returns>
        private SafeSet <Method> FilterWriteMethodsOfUpdateType(Field field,
                                                                FieldModificationType fieldModificationType, SafeSet <Method> writeMethods)
        {
            FieldStore fs;

            if (!this.FieldDictionary.TryGetValue(field, out fs))
            {
                return(writeMethods);
            }

            SafeSet <Method> returnSet = new SafeSet <Method>();

            foreach (var method in writeMethods)
            {
                //no need of methods in interfaces or abstract classes.
                TypeEx declType;
                if (method.TryGetDeclaringType(out declType) && (declType.IsAbstract || declType.IsInterface))
                {
                    continue;
                }

                //We currently allow unknown types
                FieldModificationType fmt;

                //Problem of static analysis impreciseness. If no modificuatui
                if (!fs.ModificationTypeDictionary.TryGetValue(method, out fmt))
                {
                    returnSet.Add(method);
                }

                if (fmt == fieldModificationType || fmt == FieldModificationType.UNKNOWN || fmt == FieldModificationType.METHOD_CALL)
                {
                    returnSet.Add(method);
                }
            }

            return(returnSet);
        }
        /// <summary>
        /// Parses each record and stores into internal dictionary
        /// </summary>
        /// <param name="assemblyname"></param>
        /// <param name="typename"></param>
        /// <param name="fieldname"></param>
        /// <param name="fmttype"></param>
        /// <param name="methodname"></param>
        private static void ParseRecord(IPexComponent host, string assemblyname, string typename, string fieldname, string fmttype, string methodname)
        {
            Field field;

            if (!MethodOrFieldAnalyzer.TryGetField(host, assemblyname, typename, fieldname, out field))
            {
                host.Log.LogWarning(WikiTopics.MissingWikiTopic, "PredefinedEffects", "Failed to load field: " + fieldname);
                return;
            }

            FieldModificationType fmt = FieldStore.GetModificationTypeFromString(fmttype);

            Method method;

            if (!MethodOrFieldAnalyzer.TryGetMethod(host, assemblyname, typename, methodname, out method))
            {
                host.Log.LogWarning(WikiTopics.MissingWikiTopic, "PredefinedEffects", "Failed to load method: " + methodname);
                return;
            }

            //storing into the effects store
            PreDefinedMethodEffectsStore pdme = new PreDefinedMethodEffectsStore(field, fmt);
            List <Method> suggestedMethods;
            PreDefinedMethodEffectsStore existingPdme;

            if (!effectsStore.TryGetValue(pdme, out existingPdme))
            {
                suggestedMethods         = new List <Method>();
                pdme.suggestedmethodList = suggestedMethods;
                effectsStore.Add(pdme, pdme);
            }
            else
            {
                suggestedMethods = existingPdme.suggestedmethodList;
            }

            suggestedMethods.Add(method);
        }
        /// <summary>
        /// Retrieves the write methods for a field, if exists from the predefined settings.
        /// </summary>
        public static bool TryGetWriteMethods(IPexComponent host, Field field, FieldModificationType desiredFmt,
                                              out SafeSet <Method> writeMethods)
        {
            if (!isPredefinedEffectsParsed)
            {
                ParsePredefinedEffects(host);
            }

            PreDefinedMethodEffectsStore pdme = new PreDefinedMethodEffectsStore(field, desiredFmt);
            PreDefinedMethodEffectsStore existingPdme;

            if (effectsStore.TryGetValue(pdme, out existingPdme))
            {
                writeMethods = new SafeSet <Method>();
                writeMethods.AddRange(existingPdme.suggestedmethodList);
                return(true);
            }
            else
            {
                writeMethods = null;
                return(false);
            }
        }
        /// <summary>
        /// Adds a field to an unsuccessful code location.         
        /// </summary>
        /// <param name="location"></param>
        /// <param name="fields"></param>
        public void AddFieldsOfUncoveredCodeLocations(CodeLocation location, SafeList<Field> fields, FieldModificationType fmt, 
            Term condition, string terms, int fitnessval, TypeEx explorableType, SafeList<TypeEx> allFieldTypes)
        {
            //No need to process this location.
            if (fields.Count == 0)
            {
                return;
            }

            Field targetField;
            TypeEx declaringType;   //This declaring type is considered as explorable type in the rest of the analysis
            if (!PexMeFactoryGuesser.GetTargetExplorableField(this, fields, out targetField, out declaringType))
            {
                this.Log.LogError(WikiTopics.MissingWikiTopic, "factoryguesser",
                   "Failed to retrieve the target field for uncovered location " + location.ToString());
                return;
            }

            //Compare the declaring type and actual explorable type.
            //If there is a inheritance relation, use the actual one
            if (explorableType.IsAssignableTo(declaringType))
            {
                declaringType = explorableType;
            }

            var uclskey = UncoveredCodeLocationStore.GetKey(location.ToString(), declaringType.ToString(), condition.UniqueIndex);
            UncoveredCodeLocationStoreList uclslist;
            if (!this.unCoveredLocationDic.TryGetValue(uclskey, out uclslist))
            {
                uclslist = new UncoveredCodeLocationStoreList();
                uclslist.Location = location;
                uclslist.ExplorableType = declaringType.ToString();
                uclslist.TermIndex = condition.UniqueIndex;
                this.unCoveredLocationDic[uclskey] = uclslist;
            }

            var ucls = new UncoveredCodeLocationStore();
            ucls.Location = location;
            ucls.ExplorableType = declaringType;
            ucls.TargetField = targetField;
            ucls.AllFields.AddRange(fields);
            ucls.AllFieldTypes.AddRange(allFieldTypes);
            ucls.TermIndex = condition.UniqueIndex;
            //add the sequence of method calls
            ucls.MethodCallSequence = new MethodSignatureSequence();
            foreach (var m in this.LastExecutedFactoryMethodCallSequence)
            {
                ucls.MethodCallSequence.Sequence.Add(MethodOrFieldAnalyzer.GetMethodSignature(m));
            }
            ucls.IsADefectDetectingSequence = this.DefectDetectingSequence;
            ucls.CUTMethodCallSequence = this.LastExecutedCUTMethodCallSequence;

            if (!uclslist.StoreList.Contains(ucls))
            {
                ucls.TextualTerms.Add(terms);
                ucls.DesiredFieldModificationType = fmt;
                ucls.Fitnessvalue = fitnessval;
                uclslist.StoreList.Add(ucls);
            }
        }
        /// <summary>
        /// Computes fitness values. TODO: handles only integer and boolean. Needs to be extended for other types
        /// </summary>
        /// <param name="field"></param>
        /// <param name="actual"></param>
        /// <param name="expected"></param>
        /// <param name="host"></param>
        /// <param name="fmt"></param>
        /// <param name="fitnessval"></param>
        public static void ComputeFitnessValue(Field field, FieldValueHolder actual, FieldValueHolder expected, IPexComponent host,
            out FieldModificationType fmt, out int fitnessval)
        {
            fitnessval = Int32.MaxValue;
            fmt = FieldModificationType.UNKNOWN;
            try
            {
                string fieldType = field.Type.ToString();
                if (fieldType == "System.Int32")
                {
                    fitnessval = Math.Abs(actual.intValue - expected.intValue);
                    if (actual.intValue < expected.intValue)
                    {
                        fmt = FieldModificationType.INCREMENT;
                    }
                    else if (actual.intValue > expected.intValue)
                    {
                        fmt = FieldModificationType.DECREMENT;
                    }
                    return;
                }

                if (fieldType == "System.Boolean")
                {
                    if (expected.boolValue)
                        fmt = FieldModificationType.TRUE_SET;
                    else
                        fmt = FieldModificationType.FALSE_SET;
                    return;
                }

                if (fieldType == "System.Int16")
                {
                    fitnessval = Math.Abs(actual.shortValue - expected.shortValue);
                    if (actual.shortValue < expected.shortValue)
                    {
                        fmt = FieldModificationType.INCREMENT;
                    }
                    else if (actual.shortValue > expected.shortValue)
                    {
                        fmt = FieldModificationType.DECREMENT;
                    }
                    return;
                }

                if (fieldType == "System.Int64")
                {
                    fitnessval = (int)Math.Abs(actual.longValue - expected.longValue);
                    if (actual.longValue < expected.longValue)
                    {
                        fmt = FieldModificationType.INCREMENT;
                    }
                    else if (actual.longValue > expected.longValue)
                    {
                        fmt = FieldModificationType.DECREMENT;
                    }
                    return;
                }

                if (field.Type.IsReferenceType)
                {
                    if (expected.objValue == null)
                        fmt = FieldModificationType.NULL_SET;
                    else
                        fmt = FieldModificationType.NON_NULL_SET;
                }

                host.Log.LogWarning(WikiTopics.MissingWikiTopic, "FitnexCompute", "Handles only integer and boolean types.");
            }
            catch (OverflowException ofe)
            {
                host.Log.LogCriticalFromException(ofe, WikiTopics.MissingWikiTopic, "FitnessMeasure", "Overflow error occurred while computing fitness values");
            }
        }
Exemple #13
0
        /// <summary>
        /// Computes fitness values. TODO: handles only integer and boolean. Needs to be extended for other types
        /// </summary>
        /// <param name="field"></param>
        /// <param name="actual"></param>
        /// <param name="expected"></param>
        /// <param name="host"></param>
        /// <param name="fmt"></param>
        /// <param name="fitnessval"></param>
        public static void ComputeFitnessValue(Field field, FieldValueHolder actual, FieldValueHolder expected, IPexComponent host,
                                               out FieldModificationType fmt, out int fitnessval)
        {
            fitnessval = Int32.MaxValue;
            fmt        = FieldModificationType.UNKNOWN;
            try
            {
                string fieldType = field.Type.ToString();
                if (fieldType == "System.Int32")
                {
                    fitnessval = Math.Abs(actual.intValue - expected.intValue);
                    if (actual.intValue < expected.intValue)
                    {
                        fmt = FieldModificationType.INCREMENT;
                    }
                    else if (actual.intValue > expected.intValue)
                    {
                        fmt = FieldModificationType.DECREMENT;
                    }
                    return;
                }

                if (fieldType == "System.Boolean")
                {
                    if (expected.boolValue)
                    {
                        fmt = FieldModificationType.TRUE_SET;
                    }
                    else
                    {
                        fmt = FieldModificationType.FALSE_SET;
                    }
                    return;
                }

                if (fieldType == "System.Int16")
                {
                    fitnessval = Math.Abs(actual.shortValue - expected.shortValue);
                    if (actual.shortValue < expected.shortValue)
                    {
                        fmt = FieldModificationType.INCREMENT;
                    }
                    else if (actual.shortValue > expected.shortValue)
                    {
                        fmt = FieldModificationType.DECREMENT;
                    }
                    return;
                }

                if (fieldType == "System.Int64")
                {
                    fitnessval = (int)Math.Abs(actual.longValue - expected.longValue);
                    if (actual.longValue < expected.longValue)
                    {
                        fmt = FieldModificationType.INCREMENT;
                    }
                    else if (actual.longValue > expected.longValue)
                    {
                        fmt = FieldModificationType.DECREMENT;
                    }
                    return;
                }

                if (field.Type.IsReferenceType)
                {
                    if (expected.objValue == null)
                    {
                        fmt = FieldModificationType.NULL_SET;
                    }
                    else
                    {
                        fmt = FieldModificationType.NON_NULL_SET;
                    }
                }

                host.Log.LogWarning(WikiTopics.MissingWikiTopic, "FitnexCompute", "Handles only integer and boolean types.");
            }
            catch (OverflowException ofe)
            {
                host.Log.LogCriticalFromException(ofe, WikiTopics.MissingWikiTopic, "FitnessMeasure", "Overflow error occurred while computing fitness values");
            }
        }
 /// <summary>
 /// public constructor
 /// </summary>
 /// <param name="type"></param>
 /// <param name="field"></param>
 /// <param name="fmt"></param>
 public PreDefinedMethodEffectsStore(Field field, FieldModificationType fmt)
 {
     this.field = field;
     this.fmt   = fmt;
 }
Exemple #15
0
 private static string GetModificationTypeStr(FieldModificationType fmt)
 {
     switch (fmt)
     {
         case FieldModificationType.DECREMENT: return "DECREMENT";
         case FieldModificationType.INCREMENT: return "INCREMENT";
         case FieldModificationType.INCREMENT_ONE: return "INCREMENT_ONE";
         case FieldModificationType.NULL_SET: return "NULL_SET";
         case FieldModificationType.NON_NULL_SET: return "NON_NULL_SET";
         case FieldModificationType.UNKNOWN: return "UNKNOWN";
         case FieldModificationType.TRUE_SET: return "TRUE_SET";
         case FieldModificationType.FALSE_SET: return "FALSE_SET";
         case FieldModificationType.METHOD_CALL: return "METHOD_CALL";
         default: return "UNKNOWN";
     }
 }
        /// <summary>
        /// Includes filtering of the methods based on desired format
        /// </summary>
        /// <returns></returns>
        public bool TryGetFilteredWriteMethods(Field field, TypeEx declaringType, FieldModificationType desiredfmt, out SafeSet<Method> writeMethods)
        {
            //Check in the predefined store before proceeding
            if (PreDefinedMethodEffects.TryGetWriteMethods(this, field, desiredfmt, out writeMethods))
            {
                SafeSet<Method> newWriteMethods = new SafeSet<Method>();
                GetCallingMethods(field, declaringType, writeMethods, newWriteMethods);

                //Filter those methods whose actual types are abstract
                SafeSet<Method> returnMethods = new SafeSet<Method>();
                foreach (Method m in writeMethods)
                {
                    TypeEx declType;
                    if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface)
                    {
                        returnMethods.Add(m);
                    }
                }

                foreach (Method m in newWriteMethods)
                {
                    TypeEx declType;
                    if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface)
                    {
                        returnMethods.Add(m);
                    }
                }

                writeMethods.Clear();
                writeMethods.AddRange(returnMethods);
                return true;
            }

            //Identify those method that directly modify this field
            if (!TryGetWriteMethods(field, declaringType, out writeMethods))
                return false;

            //C# supports properties. In that case, the property setter can also
            //be a viable method. add property setter and its callers also
            Property property;
            if (MethodOrFieldAnalyzer.TryGetPropertyModifyingField(this, declaringType, field, out property))
            {
                if (property.IsVisible(VisibilityContext.Exported))
                    writeMethods.Add(property.Setter);

                var newWriteMethods = new SafeSet<Method>();
                GetCallingMethods(field, declaringType, writeMethods, newWriteMethods);
                writeMethods.AddRange(newWriteMethods);
            }

            writeMethods = FilterWriteMethodsOfUpdateType(field, desiredfmt, writeMethods);
            return true;
        }
        /// <summary>
        /// Given a set of write methods, this method basically filters them out
        /// to create a new set. Also filters the method that belongs to the interface type
        /// </summary>
        /// <param name="field"></param>
        /// <param name="fieldModificationType"></param>
        /// <param name="writeMethods"></param>
        /// <returns></returns>
        private SafeSet<Method> FilterWriteMethodsOfUpdateType(Field field,
            FieldModificationType fieldModificationType, SafeSet<Method> writeMethods)
        {
            FieldStore fs;
            if (!this.FieldDictionary.TryGetValue(field, out fs))
                return writeMethods;

            SafeSet<Method> returnSet = new SafeSet<Method>();
            foreach (var method in writeMethods)
            {
                //no need of methods in interfaces or abstract classes.
                TypeEx declType;
                if (method.TryGetDeclaringType(out declType) && (declType.IsAbstract || declType.IsInterface))
                {
                    continue;
                }

                //We currently allow unknown types
                FieldModificationType fmt;

                //Problem of static analysis impreciseness. If no modificuatui
                if (!fs.ModificationTypeDictionary.TryGetValue(method, out fmt))
                    returnSet.Add(method);

                if (fmt == fieldModificationType || fmt == FieldModificationType.UNKNOWN || fmt == FieldModificationType.METHOD_CALL)
                    returnSet.Add(method);
            }

            return returnSet;
        }
Exemple #18
0
 public FloatModification(int field, float modification, bool idkbruh)
     : base(field)
 {
     _modification = modification;
     _type         = idkbruh ? FieldModificationType.RealZeroToOne : FieldModificationType.Real;
 }
        /// <summary>
        /// Checks whether there are any looping requireements based on looping threshold and enhances 
        /// the sequence accordingly. Applies only for INCREMENT and DECREMENT field modification types
        /// </summary>
        /// <param name="pucls"></param>
        /// <param name="p"></param>
        private void CheckNEnhanceForLooping(PersistentUncoveredLocationStore pucls, 
            int fitnessval, FieldModificationType fmt, SafeList<Field> culpritFields)
        {
            if (fmt != FieldModificationType.INCREMENT && fmt != FieldModificationType.DECREMENT)
                return;

            //Not even a single execution happened on this location.
            if (fitnessval == Int32.MaxValue)
                return;

            var field = culpritFields[0];
            FieldStore fs;
            if (!this.pmd.FieldDictionary.TryGetValue(field, out fs))
                return;

            Dictionary<string, Method> writeMethods = new Dictionary<string, Method>();
            foreach (var mset in fs.WriteMethods.Values)
            {
                foreach (var m in mset)
                {
                    var sig = MethodOrFieldAnalyzer.GetMethodSignature(m);
                    writeMethods.Add(sig, m);
                }
            }

            foreach (var seq in pucls.SuggestedMethodSequences)
            {
                string loop_method;
                if (!this.IsEligibleForLooping(seq, field, writeMethods, fs, out loop_method))
                    continue;

                pucls.LoopingFeatureApplied = true;
                this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "LoopingFeature",
                    "Applying looping feature on method: " + loop_method + " (" + (fitnessval - 1) + ")");
                for (int count = 1; count < fitnessval; count++)
                    seq.Sequence.Add(loop_method);
            }
        }
Exemple #20
0
        /// <summary>
        /// Adds a field to an unsuccessful code location.
        /// </summary>
        /// <param name="location"></param>
        /// <param name="fields"></param>
        public void AddFieldsOfUncoveredCodeLocations(CodeLocation location, SafeList <Field> fields, FieldModificationType fmt,
                                                      Term condition, string terms, int fitnessval, TypeEx explorableType, SafeList <TypeEx> allFieldTypes)
        {
            //No need to process this location.
            if (fields.Count == 0)
            {
                return;
            }

            Field  targetField;
            TypeEx declaringType;   //This declaring type is considered as explorable type in the rest of the analysis

            if (!PexMeFactoryGuesser.GetTargetExplorableField(this, fields, out targetField, out declaringType))
            {
                this.Log.LogError(WikiTopics.MissingWikiTopic, "factoryguesser",
                                  "Failed to retrieve the target field for uncovered location " + location.ToString());
                return;
            }

            //Compare the declaring type and actual explorable type.
            //If there is a inheritance relation, use the actual one
            if (explorableType.IsAssignableTo(declaringType))
            {
                declaringType = explorableType;
            }

            var uclskey = UncoveredCodeLocationStore.GetKey(location.ToString(), declaringType.ToString(), condition.UniqueIndex);
            UncoveredCodeLocationStoreList uclslist;

            if (!this.unCoveredLocationDic.TryGetValue(uclskey, out uclslist))
            {
                uclslist                           = new UncoveredCodeLocationStoreList();
                uclslist.Location                  = location;
                uclslist.ExplorableType            = declaringType.ToString();
                uclslist.TermIndex                 = condition.UniqueIndex;
                this.unCoveredLocationDic[uclskey] = uclslist;
            }

            var ucls = new UncoveredCodeLocationStore();

            ucls.Location       = location;
            ucls.ExplorableType = declaringType;
            ucls.TargetField    = targetField;
            ucls.AllFields.AddRange(fields);
            ucls.AllFieldTypes.AddRange(allFieldTypes);
            ucls.TermIndex = condition.UniqueIndex;
            //add the sequence of method calls
            ucls.MethodCallSequence = new MethodSignatureSequence();
            foreach (var m in this.LastExecutedFactoryMethodCallSequence)
            {
                ucls.MethodCallSequence.Sequence.Add(MethodOrFieldAnalyzer.GetMethodSignature(m));
            }
            ucls.IsADefectDetectingSequence = this.DefectDetectingSequence;
            ucls.CUTMethodCallSequence      = this.LastExecutedCUTMethodCallSequence;

            if (!uclslist.StoreList.Contains(ucls))
            {
                ucls.TextualTerms.Add(terms);
                ucls.DesiredFieldModificationType = fmt;
                ucls.Fitnessvalue = fitnessval;
                uclslist.StoreList.Add(ucls);
            }
        }
        /// <summary>
        /// OBSOLETE:
        /// </summary>
        /// <param name="termManager"></param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="binOp"></param>
        /// <param name="bNegated"></param>
        /// <param name="culpritFields"></param>
        /// <param name="completeTerm"></param>
        /// <param name="fmt"></param>
        /// <param name="fitnessval"></param>
        private void handleNoConstantsInTerm(TermManager termManager, Term left, Term right, BinaryOperator binOp,
            bool bNegated, SafeList<Field> culpritFields, Term completeTerm, out FieldModificationType fmt, out int fitnessval)
        {
            fmt = FieldModificationType.UNKNOWN;
            //Term termUnderAnalysis = null;
            //Term otherTerm = null;

            //Field instanceField;
            //if (termManager.TryGetInstanceField(left, out instanceField) && culpritFields.Contains(instanceField))
            //{
            //    termUnderAnalysis = left;
            //    otherTerm = right;
            //}
            //else
            //{
            //    if (termManager.TryGetInstanceField(right, out instanceField))
            //        if (culpritFields.Contains(instanceField))
            //        {
            //            termUnderAnalysis = right;
            //            otherTerm = left;
            //        }
            //}

            //if (termUnderAnalysis == null)
            //    return;

            //object value;
            //if (termManager.TryGetObject(left, out value))
            //{
            //    if (value == null && binOp == BinaryOperator.Ceq)
            //    {
            //        fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET;
            //    }
            //    else if (value is int || value is Int16 || value is Int32 || value is Int64)
            //    {
            //        fmt = FieldModificationType.INCREMENT; //TODO: Needs to get actual values and decide based on that
            //    }
            //} else if (termManager.TryGetObject(right, out value))
            //{
            //    if (value == null && binOp == BinaryOperator.Ceq)
            //    {
            //        fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET;
            //    }
            //    else if (value is int || value is Int16 || value is Int32 || value is Int64)
            //    {
            //        fmt = FieldModificationType.INCREMENT; //TODO: Needs to get actual values and decide based on that
            //    }
            //}

            //TODO: A worst fix to proceed further
            fitnessval = Int32.MaxValue;
            if (culpritFields.Count == 0)
                return;
            var culprittype = culpritFields[0].Type;
            if (culprittype.IsReferenceType)
                fmt = FieldModificationType.NON_NULL_SET;
            else
            {
                var typestr = culprittype.ToString();
                if (typestr == "System.Boolean")
                    fmt = FieldModificationType.TRUE_SET;
                else if (typestr == "System.Int32" || typestr == "System.Int64" || typestr == "System.Int16")
                {
                    SafeDictionary<Field, FieldValueHolder> fieldValues;
                    //TermSolver.SolveTerm(this.ter, completeTerm, out fieldValues);
                    fmt = FieldModificationType.INCREMENT;
                }
            }
        }
Exemple #22
0
        /// <summary>
        /// OBSOLETE: Handles a scenario where there is a term in the condition
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="binOp"></param>
        /// <param name="fmt"></param>
        private void handleAConstantInTerm(TermManager termManager, Term left, Term right,
                                           BinaryOperator binOp, bool bNegated, SafeDictionary <Field, FieldValueHolder> fieldValues, Field culpritField,
                                           out FieldModificationType fmt, out int fitnessval)
        {
            fitnessval = Int32.MaxValue;
            fmt        = FieldModificationType.UNKNOWN;
            Term non_constant_term = null;
            Term constant_term     = null;

            bool bleftRightMaintainted = true;

            if (termManager.IsValue(left))
            {
                non_constant_term     = right;
                constant_term         = left;
                bleftRightMaintainted = true;
            }
            else if (termManager.IsValue(right))
            {
                non_constant_term     = left;
                constant_term         = right;
                bleftRightMaintainted = false;
            }

            int value;

            if (termManager.TryGetI4Constant(constant_term, out value))
            {
                fmt = FieldModificationType.INCREMENT;

                FieldValueHolder fvh;
                if (fieldValues.TryGetValue(culpritField, out fvh))
                {
                    int non_constant_field_value = fvh.intValue;    //TODO: Assuming that the fieldType is Int32
                    if (bleftRightMaintainted)
                    {
                        fitnessval = FitnessMeasure.ComputeFitnessValue(this.host, binOp, value, non_constant_field_value, bNegated);
                    }
                    else
                    {
                        fitnessval = FitnessMeasure.ComputeFitnessValue(this.host, binOp, non_constant_field_value, value, bNegated);
                    }
                }
                else
                {
                    this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fitness measure",
                                             "Failed to retrieve value for field " + culpritField.ToString());
                }
            }
            else if (termManager.IsDefaultValue(constant_term))
            {
                if (binOp == BinaryOperator.Ceq)
                {
                    if (culpritField.Type.ToString() == "System.Boolean")
                    {
                        fmt = bNegated ? FieldModificationType.TRUE_SET : FieldModificationType.FALSE_SET;
                    }
                    else
                    {
                        fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET;
                    }
                }
            }

            Term           objectValue;
            ObjectProperty objectProperty;

            if (termManager.TryGetObjectProperty(constant_term, out objectValue, out objectProperty))
            {
                //TODO??? How to handle this scenario?
            }
        }
 /// <summary>
 /// Checks whether fitness strategy matters or not. Since, fitness
 /// is required only for integers, but not for all kinds of types such
 /// as boolean or non-null
 /// </summary>
 /// <returns></returns>
 private bool IsFitnessRequired(FieldModificationType fmt)
 {
     switch (fmt)
     {
         case FieldModificationType.INCREMENT:
         case FieldModificationType.DECREMENT:
         case FieldModificationType.INCREMENT_ONE:
             return true;
         case FieldModificationType.FALSE_SET:
         case FieldModificationType.TRUE_SET:
         case FieldModificationType.NULL_SET:
         case FieldModificationType.NON_NULL_SET:
             return false;
         default:
             return false;
     }
 }
Exemple #24
0
        /// <summary>
        /// OBSOLETE:
        /// </summary>
        /// <param name="termManager"></param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="binOp"></param>
        /// <param name="bNegated"></param>
        /// <param name="culpritFields"></param>
        /// <param name="completeTerm"></param>
        /// <param name="fmt"></param>
        /// <param name="fitnessval"></param>
        private void handleNoConstantsInTerm(TermManager termManager, Term left, Term right, BinaryOperator binOp,
                                             bool bNegated, SafeList <Field> culpritFields, Term completeTerm, out FieldModificationType fmt, out int fitnessval)
        {
            fmt = FieldModificationType.UNKNOWN;
            //Term termUnderAnalysis = null;
            //Term otherTerm = null;

            //Field instanceField;
            //if (termManager.TryGetInstanceField(left, out instanceField) && culpritFields.Contains(instanceField))
            //{
            //    termUnderAnalysis = left;
            //    otherTerm = right;
            //}
            //else
            //{
            //    if (termManager.TryGetInstanceField(right, out instanceField))
            //        if (culpritFields.Contains(instanceField))
            //        {
            //            termUnderAnalysis = right;
            //            otherTerm = left;
            //        }
            //}

            //if (termUnderAnalysis == null)
            //    return;

            //object value;
            //if (termManager.TryGetObject(left, out value))
            //{
            //    if (value == null && binOp == BinaryOperator.Ceq)
            //    {
            //        fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET;
            //    }
            //    else if (value is int || value is Int16 || value is Int32 || value is Int64)
            //    {
            //        fmt = FieldModificationType.INCREMENT; //TODO: Needs to get actual values and decide based on that
            //    }
            //} else if (termManager.TryGetObject(right, out value))
            //{
            //    if (value == null && binOp == BinaryOperator.Ceq)
            //    {
            //        fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET;
            //    }
            //    else if (value is int || value is Int16 || value is Int32 || value is Int64)
            //    {
            //        fmt = FieldModificationType.INCREMENT; //TODO: Needs to get actual values and decide based on that
            //    }
            //}

            //TODO: A worst fix to proceed further
            fitnessval = Int32.MaxValue;
            if (culpritFields.Count == 0)
            {
                return;
            }
            var culprittype = culpritFields[0].Type;

            if (culprittype.IsReferenceType)
            {
                fmt = FieldModificationType.NON_NULL_SET;
            }
            else
            {
                var typestr = culprittype.ToString();
                if (typestr == "System.Boolean")
                {
                    fmt = FieldModificationType.TRUE_SET;
                }
                else if (typestr == "System.Int32" || typestr == "System.Int64" || typestr == "System.Int16")
                {
                    SafeDictionary <Field, FieldValueHolder> fieldValues;
                    //TermSolver.SolveTerm(this.ter, completeTerm, out fieldValues);
                    fmt = FieldModificationType.INCREMENT;
                }
            }
        }
        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>
        /// OBSOLETE: Handles a scenario where there is a term in the condition
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="binOp"></param>
        /// <param name="fmt"></param>
        private void handleAConstantInTerm(TermManager termManager, Term left, Term right,
            BinaryOperator binOp, bool bNegated, SafeDictionary<Field, FieldValueHolder> fieldValues, Field culpritField,
            out FieldModificationType fmt, out int fitnessval)
        {
            fitnessval = Int32.MaxValue;
            fmt = FieldModificationType.UNKNOWN;
            Term non_constant_term = null;
            Term constant_term = null;

            bool bleftRightMaintainted = true;
            if (termManager.IsValue(left))
            {
                non_constant_term = right;
                constant_term = left;
                bleftRightMaintainted = true;
            }
            else if (termManager.IsValue(right))
            {
                non_constant_term = left;
                constant_term = right;
                bleftRightMaintainted = false;
            }

            int value;
            if (termManager.TryGetI4Constant(constant_term, out value))
            {
                fmt = FieldModificationType.INCREMENT;

                FieldValueHolder fvh;
                if (fieldValues.TryGetValue(culpritField, out fvh))
                {
                    int non_constant_field_value = fvh.intValue;    //TODO: Assuming that the fieldType is Int32
                    if (bleftRightMaintainted)
                        fitnessval = FitnessMeasure.ComputeFitnessValue(this.host, binOp, value, non_constant_field_value, bNegated);
                    else
                        fitnessval = FitnessMeasure.ComputeFitnessValue(this.host, binOp, non_constant_field_value, value, bNegated);
                }
                else
                    this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fitness measure",
                        "Failed to retrieve value for field " + culpritField.ToString());
            }
            else if (termManager.IsDefaultValue(constant_term))
            {
                if (binOp == BinaryOperator.Ceq)
                {
                    if (culpritField.Type.ToString() == "System.Boolean")
                    {
                        fmt = bNegated ? FieldModificationType.TRUE_SET : FieldModificationType.FALSE_SET;
                    }
                    else
                        fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET;
                }
            }

            Term objectValue;
            ObjectProperty objectProperty;
            if (termManager.TryGetObjectProperty(constant_term, out objectValue, out objectProperty))
            {
                //TODO??? How to handle this scenario?
            }
        }