Пример #1
0
 /// <summary>
 /// Loads a plan into the lookup dictionary.
 /// </summary>
 /// <param name="plan">A <see cref="TrapPlan" />.</param>
 public void AddPlan(TrapPlan plan)
 {
     if (plan != null)
     {
         if (plan.API.Contains("*") || plan.Method.Contains("*"))
         {
             this.wildCardPlans.Add(plan);
         }
         else
         {
             string planId = plan.GetID();
             if (this.nonwildCardPlans.ContainsKey(planId))
             {
                 if (plan.HitCounts != null)
                 {
                     this.nonwildCardPlans[planId].HitCounts.AddRange(plan.HitCounts);
                 }
             }
             else
             {
                 this.nonwildCardPlans[planId] = plan;
             }
         }
     }
 }
Пример #2
0
        /// <summary>
        /// Finds a matching <see cref="TrapPlan" />.
        /// </summary>
        /// <param name="interceptionPoint">CUrrent InterceptionPoint.</param>
        /// <param name="globalHitcountWindow">Global hitcount window.</param>
        /// <param name="localHitcountWindow">Local hitcount window.</param>
        /// <returns>A matching <see cref="TrapPlan" />.</returns>
        public TrapPlan FindMatchingPlan(InterceptionPoint interceptionPoint, int globalHitcountWindow = 20, int localHitcountWindow = 5)
        {
            if (interceptionPoint == null || interceptionPoint.API == null)
            {
                return(null);
            }

            var planId = TrapPlan.GetID(interceptionPoint.API, interceptionPoint.Method, interceptionPoint.ILOffset);

            if (this.nonwildCardPlans.ContainsKey(planId))
            {
                var  plan    = this.nonwildCardPlans[planId];
                bool isMatch = (plan.ThreadId == null || string.Equals(plan.ThreadId, interceptionPoint.ThreadId)) &&
                               (plan.HitCounts == null || plan.HitCounts.Count(x => x.IsMatch(interceptionPoint.LocalHitcount, localHitcountWindow, interceptionPoint.GLobalHitCount, globalHitcountWindow)) > 0);

                return(isMatch ? plan : null);
            }

            foreach (var plan in this.wildCardPlans)
            {
                if (!SignatureMatchUtils.IsWildcardMatch(interceptionPoint.API, plan.API))
                {
                    continue;
                }

                if (plan.Method != null && !SignatureMatchUtils.IsWildcardMatch(interceptionPoint.Method, plan.Method))
                {
                    continue;
                }

                if (plan.ILOffset >= 0 && plan.ILOffset != interceptionPoint.ILOffset)
                {
                    continue;
                }

                if (plan.ThreadId != null && !string.Equals(plan.ThreadId, interceptionPoint.ThreadId))
                {
                    continue;
                }

                if (plan.HitCounts != null && plan.HitCounts.Count(x => x.IsMatch(interceptionPoint.LocalHitcount, localHitcountWindow, interceptionPoint.GLobalHitCount, globalHitcountWindow)) > 0)
                {
                    continue;
                }

                return(plan);
            }

            return(null);
        }
Пример #3
0
        /// <summary>
        /// Adds the new plan.
        /// </summary>
        /// <param name="interceptionPointInfo">The InterceptionPoint information.</param>
        /// <param name="frequency">The frequency.</param>
        private void AddNewPlan(string interceptionPointInfo, int frequency)
        {
            TrapPlan trapPlan = new TrapPlan();

            string[] tokens = interceptionPointInfo.Split('|');
            trapPlan.API      = tokens[0];
            trapPlan.Method   = tokens[1];
            trapPlan.ILOffset = int.Parse(tokens[2]);
            trapPlan.AddHitCount(int.Parse(tokens[4]), int.Parse(tokens[3]));
            trapPlan.FixedDelayMs = this.DelayPerDangerousInterceptionPoint;
            trapPlan.Repeat       = frequency > 1;
            lock (this.TrapPlans)
            {
                this.TrapPlans.AddPlan(trapPlan);
            }
        }
Пример #4
0
        /// <summary>
        /// Checks for bugs and start trap.
        /// </summary>
        /// <param name="interceptionPoint">The InterceptionPoint.</param>
        /// <param name="threadSafetyInterceptionPoint">The thread safety InterceptionPoint.</param>
        /// <param name="trapObjects">The trap objects.</param>
        /// <param name="trapPlan">The trap plan.</param>
        /// <param name="instance">The instance.</param>
        /// <param name="bugFound">If set to <see langword="true" /> then a bug has been found.</param>
        /// <returns>Trap.</returns>
        private Trap CheckForBugsAndStartTrap(InterceptionPoint interceptionPoint, ThreadSafetyInterceptionPoint threadSafetyInterceptionPoint, Dictionary <Guid, HashSet <Trap> > trapObjects, TrapPlan trapPlan, object instance, out bool bugFound)
        {
            int       danger           = -1;
            Semaphore semaphore        = null;
            double    prob             = 1.0;
            int       sleepDuration    = 0;
            Guid      objectId         = interceptionPoint.ObjID;
            bool      continueAfterBug = false;

            bugFound = false;
            Trap newTrap = null;

            lock (trapObjects)
            {
                // Check if a thread-safety bug is found
                if (trapObjects.ContainsKey(objectId))
                {
                    foreach (Trap trap in trapObjects[objectId])
                    {
                        ThreadSafetyInterceptionPoint runningTP = this.GetThreadSafetyInterceptionPoint(trap.InterceptionPoint);
                        if (threadSafetyInterceptionPoint.IsWriteAPI || runningTP.IsWriteAPI)
                        {
                            bugFound = true;
                            interceptionPoint.StackTrace = Environment.StackTrace;

                            // DebugLog.Log("HitBug " + InterceptionPoint.Tostring() + " " + runningt.InterceptionPoint.Tostring());
                            ControllerHelper.WriteBug(trap, interceptionPoint);
                            this.LogBugForNextRun(interceptionPoint, trap.InterceptionPoint);

                            // For some InterceptionPoints, keep execution even hitting a bug. It may expose more bugs.
                            if ((trapPlan != null) && (!trapPlan.Repeat))
                            {
                                continueAfterBug = true;
                            }
                        }
                    }
                }

                if (bugFound && (!continueAfterBug))
                {
                    // DebugLog.Log("HIt Bug and exit " + InterceptionPoint.Tostring());
                    return(null);
                }

                // else
                {
                    // check if the InterceptionPoint match with dangerous list
                    danger = this.IsInsideDangerList(interceptionPoint.Location);

                    if ((danger < 0) && (!interceptionPoint.IsInPlan))
                    {
                        // exit when not matching and not in the plan
                        return(null);
                    }

                    // prepare to set up a trap if (threadSafetyInterceptionPoint.IsWriteAPI && !this.isTrapActive)
                    if ((!this.isTrapActive || (danger >= 0) || interceptionPoint.IsInPlan) && ((trapPlan != null) || threadSafetyInterceptionPoint.IsWriteAPI))
                    {
                        prob = trapPlan != null ? trapPlan.DelayProbability : this.DelayProbability;

                        if (danger >= 0)
                        {
                            prob = this.DelayProbabilityAtDangerousInterceptionPoint - (this.DecayFactor * danger);
                        }

                        if (this.random.NextDouble() <= prob)
                        {
                            // Get stack trace only if setting up a trap.
                            interceptionPoint.StackTrace = Environment.StackTrace;

                            semaphore     = new Semaphore(0, 1);
                            sleepDuration = trapPlan == null?
                                            this.random.Next(this.MaxDelayPerInterceptionPoint)
                                                : trapPlan.FixedDelayMs;

                            if (danger >= 0)
                            {
                                sleepDuration = this.DelayPerDangerousInterceptionPoint;
                            }

                            newTrap = new Trap
                            {
                                ObjectId          = objectId,
                                Semaphore         = semaphore,
                                InterceptionPoint = interceptionPoint,
                                Delay             = sleepDuration,
                            };

                            ControllerHelper.WriteTrap(newTrap);

                            if (!trapObjects.ContainsKey(objectId))
                            {
                                trapObjects.Add(objectId, new HashSet <Trap>());
                            }

                            trapObjects[objectId].Add(newTrap);

                            this.isTrapActive = true;
                        }
                    }
                }
            }

            return(newTrap);
        }
Пример #5
0
        /// <summary>
        /// Converts to rchpointstart.
        /// </summary>
        /// <param name="interceptionPoint">The InterceptionPoint.</param>
        /// <param name="instance">The instance.</param>
        /// <param name="parameters">The parameters.</param>
        /// </summary>
        public void InterceptionPointStart(InterceptionPoint interceptionPoint, object instance = null, object[] parameters = null)
        {
            /*
             * I add more field variables to help the analysis. They are initialized in the constructor.
             * when hitting a new InterceptionPoint here are the procedures in the implementation:
             * 1.assign the hit-seq for InterceptionPoint
             * 2.assign the global id for InterceptionPoint. It is duplicated with InterceptionPoint.id.
             * 3.update the InterceptionPoints history to infer the concurrent threads.
             * 4.find the dangerous pair for this InterceptionPoint
             * 5.find the the opeartion set that happens-before this InterceptionPoint
             * 6.check if find a bug
             * 7.construct the trap
             * 8.execute the trap
             * 9.locate the threads that are blocked by this trap
             */
            var newBugFound = false;

            if (this.configuration == null || this.configuration.ThreadSafetyGroups == null)
            {
                return;
            }

            this.UpdateTPHitCounts(interceptionPoint);

            TrapPlan trapPlan = this.TrapPlans.FindMatchingPlan(interceptionPoint, this.GlobalHitcountWindow, this.LocalHitcountWindow);

            interceptionPoint.IsInPlan = trapPlan != null;

            this.UpdateTPHistory(interceptionPoint);

            // This block is used for monitoring the lock.Now we can just skip the lock operations. this.Updatelockinformation(InterceptionPoint);
            if (this.LockRelatedOP(interceptionPoint))
            {
                return;
            }

            // Locate the APIs bypass the lock operation
            ThreadSafetyInterceptionPoint threadSafetyInterceptionPoint = this.GetThreadSafetyInterceptionPoint(interceptionPoint);

            if (threadSafetyInterceptionPoint == null ||
                (!threadSafetyInterceptionPoint.ThreadSafetyGroup.IsStatic && instance == null))
            {
                return;
            }

            // update the write/read InterceptionPoint
            interceptionPoint.IsWrite = threadSafetyInterceptionPoint.IsWriteAPI;

            interceptionPoint.ObjID = threadSafetyInterceptionPoint.ThreadSafetyGroup.IsStatic ? ObjectId.GetRefId(null) : ObjectId.GetRefId(instance);

            // this block will looking for the near-miss pair and learn the dependency.
            if ((interceptionPoint.IsInPlan == false) && (this.DetectDangerousPairs == true))
            {
                this.FindRacingTP(interceptionPoint);
                this.RemoveDependentInterceptionPoints(interceptionPoint);
            }

            var trapObjects = this.GetTrapObjects(threadSafetyInterceptionPoint);

            Trap trap = this.CheckForBugsAndStartTrap(interceptionPoint, threadSafetyInterceptionPoint, trapObjects, trapPlan, instance, out newBugFound);

            if (trap == null)
            {
                return;
            }

            this.FinishTrap(trapObjects, trap, interceptionPoint);

            if (this.configuration.ThrowExceptionOnRace & newBugFound)
            {
                throw new Exception("ThreadSafety bugs detected by TSVD");
            }

            return;
        }
Пример #6
0
 /// <summary>
 /// Gets the identifier.
 /// </summary>
 /// <returns>System.String.</returns>
 public string GetID()
 {
     return(TrapPlan.GetID(this.API, this.Method, this.ILOffset));
 }