Esempio n. 1
0
            protected override void UpdateValuesForAnalysisData(CopyAnalysisData targetAnalysisData)
            {
                // We need to trim the copy values to only include the entities that are existing keys in targetAnalysisData.
                var processedEntities = PooledHashSet <AnalysisEntity> .GetInstance();

                var builder = ArrayBuilder <AnalysisEntity> .GetInstance(targetAnalysisData.CoreAnalysisData.Count);

                try
                {
                    builder.AddRange(targetAnalysisData.CoreAnalysisData.Keys);
                    for (int i = 0; i < builder.Count; i++)
                    {
                        var key = builder[i];
                        if (!processedEntities.Add(key))
                        {
                            continue;
                        }

                        if (CurrentAnalysisData.TryGetValue(key, out var newValue))
                        {
                            var existingValue = targetAnalysisData[key];
                            if (newValue.AnalysisEntities.Count == 1)
                            {
                                if (existingValue.AnalysisEntities.Count == 1)
                                {
                                    continue;
                                }
                            }
                            else if (newValue.AnalysisEntities.Count > 1)
                            {
                                var entitiesToExclude = newValue.AnalysisEntities.Where(e => !targetAnalysisData.HasAbstractValue(e));
                                if (entitiesToExclude.Any())
                                {
                                    newValue = newValue.WithEntitiesRemoved(entitiesToExclude);
                                }
                            }

                            if (newValue != existingValue)
                            {
                                targetAnalysisData.SetAbstactValueForEntities(newValue, entityBeingAssignedOpt: null);
                            }

                            processedEntities.AddRange(newValue.AnalysisEntities);
                        }
                    }
                }
                finally
                {
                    processedEntities.Free();
                    builder.Free();
                }
            }
Esempio n. 2
0
            private void HandlePossibleEscapingOperation(IOperation escapingOperation, IOperation escapedInstance)
            {
                PointsToAbstractValue pointsToValue = GetPointsToAbstractValue(escapedInstance);

                foreach (AbstractLocation location in pointsToValue.Locations)
                {
                    if (CurrentAnalysisData.TryGetValue(location, out DisposeAbstractValue currentDisposeValue))
                    {
                        DisposeAbstractValue newDisposeValue = currentDisposeValue.WithNewEscapingOperation(escapingOperation);
                        SetAbstractValue(location, newDisposeValue);
                    }
                }
            }
            private void HandlePossibleInvalidatingOperation(IOperation invalidatedInstance)
            {
                PointsToAbstractValue instanceLocation = GetPointsToAbstractValue(invalidatedInstance);

                foreach (AbstractLocation location in instanceLocation.Locations)
                {
                    if (CurrentAnalysisData.TryGetValue(location, out DisposeAbstractValue currentDisposeValue) &&
                        currentDisposeValue.Kind != DisposeAbstractValueKind.NotDisposable)
                    {
                        SetAbstractValue(location, DisposeAbstractValue.Invalid);
                    }
                }
            }
Esempio n. 4
0
            protected override PointsToAbstractValue GetAbstractValue(AnalysisEntity analysisEntity)
            {
                if (!ShouldBeTracked(analysisEntity.Type))
                {
                    return(PointsToAbstractValue.NoLocation);
                }

                if (!CurrentAnalysisData.TryGetValue(analysisEntity, out var value))
                {
                    value = _defaultPointsToValueGenerator.GetOrCreateDefaultValue(analysisEntity);
                }

                return(value);
            }
            protected override PredicateValueKind SetValueForEqualsOrNotEqualsComparisonOperator(IBinaryOperation operation, CopyAnalysisData negatedCurrentAnalysisData, bool equals)
            {
                Debug.Assert(operation.IsComparisonOperator());

                if (GetCopyAbstractValue(operation.LeftOperand).Kind != CopyAbstractValueKind.Unknown &&
                    GetCopyAbstractValue(operation.RightOperand).Kind != CopyAbstractValueKind.Unknown &&
                    AnalysisEntityFactory.TryCreate(operation.LeftOperand, out AnalysisEntity leftEntity) &&
                    AnalysisEntityFactory.TryCreate(operation.RightOperand, out AnalysisEntity rightEntity))
                {
                    var predicateKind = PredicateValueKind.Unknown;
                    if (!CurrentAnalysisData.TryGetValue(rightEntity, out CopyAbstractValue rightValue))
                    {
                        rightValue = new CopyAbstractValue(rightEntity);
                    }
                    else if (rightValue.AnalysisEntities.Contains(leftEntity))
                    {
                        // We have "a == b && a == b" or "a == b && a != b"
                        // For both cases, condition on right is always true or always false and redundant.
                        predicateKind = equals ? PredicateValueKind.AlwaysTrue : PredicateValueKind.AlwaysFalse;
                    }
                    else if (negatedCurrentAnalysisData.TryGetValue(rightEntity, out var negatedRightValue) &&
                             negatedRightValue.AnalysisEntities.Contains(leftEntity))
                    {
                        // We have "a == b || a == b" or "a == b || a != b"
                        // For both cases, condition on right is always true or always false and redundant.
                        predicateKind = equals ? PredicateValueKind.AlwaysFalse : PredicateValueKind.AlwaysTrue;
                    }

                    if (predicateKind != PredicateValueKind.Unknown)
                    {
                        if (!equals)
                        {
                            // "a == b && a != b" or "a == b || a != b"
                            // CurrentAnalysisData and negatedCurrentAnalysisData are both unknown values.
                            foreach (var entity in rightValue.AnalysisEntities)
                            {
                                SetAbstractValue(CurrentAnalysisData, entity, CopyAbstractValue.Invalid, fromPredicate: true);
                                SetAbstractValue(negatedCurrentAnalysisData, entity, CopyAbstractValue.Invalid, fromPredicate: true);
                            }
                        }

                        return(predicateKind);
                    }

                    var analysisData = equals ? CurrentAnalysisData : negatedCurrentAnalysisData;
                    SetAbstractValue(analysisData, leftEntity, rightValue, fromPredicate: true);
                }

                return(PredicateValueKind.Unknown);
            }
Esempio n. 6
0
            protected override PointsToAbstractValue GetAbstractValue(AnalysisEntity analysisEntity)
            {
                if (analysisEntity.Type.HasValueCopySemantics())
                {
                    return(PointsToAbstractValue.NoLocation);
                }

                if (!CurrentAnalysisData.TryGetValue(analysisEntity, out var value))
                {
                    value = analysisEntity.SymbolOpt?.Kind == SymbolKind.Local ?
                            ValueDomain.Bottom :
                            ValueDomain.UnknownOrMayBeValue;
                }

                return(value);
            }
Esempio n. 7
0
            protected override void SetValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity, ArgumentInfo <CopyAbstractValue> assignedValueOpt)
            {
                CopyAbstractValue copyValue;

                if (assignedValueOpt != null)
                {
                    var assignedEntities = assignedValueOpt.Value.AnalysisEntities;
                    if (assignedValueOpt.AnalysisEntityOpt != null && !assignedEntities.Contains(assignedValueOpt.AnalysisEntityOpt))
                    {
                        assignedEntities = assignedEntities.Add(assignedValueOpt.AnalysisEntityOpt);
                    }

                    var newAnalysisEntities = assignedEntities;
                    CopyAbstractValueKind newKind;
                    if (assignedValueOpt.Value.Kind.IsKnown())
                    {
                        newKind = assignedValueOpt.Value.Kind;
                    }
                    else if (assignedValueOpt.AnalysisEntityOpt == null || assignedValueOpt.AnalysisEntityOpt.Type.IsValueType)
                    {
                        newKind = CopyAbstractValueKind.KnownValueCopy;
                    }
                    else
                    {
                        newKind = CopyAbstractValueKind.KnownReferenceCopy;
                    }

                    foreach (var entity in assignedEntities)
                    {
                        if (CurrentAnalysisData.TryGetValue(entity, out var existingValue))
                        {
                            newAnalysisEntities = newAnalysisEntities.Union(existingValue.AnalysisEntities);
                            newKind             = newKind.MergeIfBothKnown(existingValue.Kind);
                        }
                    }

                    copyValue = assignedValueOpt.Value.AnalysisEntities.Count == newAnalysisEntities.Count ?
                                assignedValueOpt.Value :
                                new CopyAbstractValue(newAnalysisEntities, newKind);
                }
                else
                {
                    copyValue = GetDefaultCopyValue(analysisEntity);
                }

                SetAbstractValue(CurrentAnalysisData, analysisEntity, copyValue, TryGetAddressSharedCopyValue, initializingParameters: true);
            }
            private void SetValueForComparisonOperator(IOperation target, IOperation assignedValue, bool equals, ref PredicateValueKind predicateValueKind, ValueContentAnalysisData targetAnalysisData)
            {
                ValueContentAbstractValue currentAssignedValue = GetCachedAbstractValue(assignedValue);

                if (currentAssignedValue.IsLiteralState &&
                    AnalysisEntityFactory.TryCreate(target, out AnalysisEntity targetEntity))
                {
                    if (CurrentAnalysisData.TryGetValue(targetEntity, out ValueContentAbstractValue existingTargetValue) &&
                        existingTargetValue.IsLiteralState)
                    {
                        var newValue = currentAssignedValue.IntersectLiteralValues(existingTargetValue);
                        if (newValue.NonLiteralState == ValueContainsNonLiteralState.Invalid)
                        {
                            predicateValueKind = equals ? PredicateValueKind.AlwaysFalse : PredicateValueKind.AlwaysTrue;
                        }
                        else if (predicateValueKind != PredicateValueKind.AlwaysFalse &&
                                 newValue.IsLiteralState &&
                                 newValue.LiteralValues.Count == 1 &&
                                 currentAssignedValue.LiteralValues.Count == 1 &&
                                 existingTargetValue.LiteralValues.Count == 1)
                        {
                            predicateValueKind = equals ? PredicateValueKind.AlwaysTrue : PredicateValueKind.AlwaysFalse;
                        }

                        currentAssignedValue = newValue;
                    }

                    if (equals)
                    {
                        CopyAbstractValue copyValue = GetCopyAbstractValue(target);
                        if (copyValue.Kind.IsKnown())
                        {
                            // https://github.com/dotnet/roslyn-analyzers/issues/2106 tracks enabling the below assert.
                            //Debug.Assert(copyValue.AnalysisEntities.Contains(targetEntity));
                            foreach (var analysisEntity in copyValue.AnalysisEntities)
                            {
                                SetAbstractValue(targetAnalysisData, analysisEntity, currentAssignedValue);
                            }
                        }
                        else
                        {
                            SetAbstractValue(targetAnalysisData, targetEntity, currentAssignedValue);
                        }
                    }
                }
            }
            private void HandleDisposingOperation(IOperation disposingOperation, IOperation disposedInstance)
            {
                if (disposedInstance.Type?.IsDisposable(IDisposableNamedType) == false)
                {
                    return;
                }

                PointsToAbstractValue instanceLocation = GetPointsToAbstractValue(disposedInstance);

                foreach (AbstractLocation location in instanceLocation.Locations)
                {
                    if (CurrentAnalysisData.TryGetValue(location, out DisposeAbstractValue currentDisposeValue))
                    {
                        DisposeAbstractValue disposeValue = currentDisposeValue.WithNewDisposingOperation(disposingOperation);
                        SetAbstractValue(location, disposeValue);
                    }
                }
            }
Esempio n. 10
0
            private void HandlePossibleEscapingOperation(IOperation escapingOperation, IOperation escapedInstance)
            {
                if (escapedInstance?.Type == null ||
                    !escapedInstance.Type.IsDisposable(_iDisposable))
                {
                    return;
                }

                PointsToAbstractValue instanceLocation = GetPointsToAbstractValue(escapedInstance);

                foreach (AbstractLocation location in instanceLocation.Locations)
                {
                    if (CurrentAnalysisData.TryGetValue(location, out DisposeAbstractValue currentDisposeValue))
                    {
                        DisposeAbstractValue newDisposeValue = currentDisposeValue.WithNewEscapingOperation(escapingOperation);
                        SetAbstractValue(location, newDisposeValue);
                    }
                }
            }
            private bool IsTrackedLocation(AbstractLocation location)
            {
                return(CurrentAnalysisData.ContainsKey(location) ||
                       location.SymbolOpt is IParameterSymbol parameter &&
                       parameter.Type.IsReferenceType &&
                       Equals(parameter.ContainingSymbol, GetBottomOfStackOwningSymbol()));

                ISymbol GetBottomOfStackOwningSymbol()
                {
                    if (DataFlowAnalysisContext.InterproceduralAnalysisDataOpt == null)
                    {
                        return(OwningSymbol);
                    }

                    return(DataFlowAnalysisContext.InterproceduralAnalysisDataOpt.MethodsBeingAnalyzed
                           .Single(m => m.InterproceduralAnalysisDataOpt == null)
                           .OwningSymbol);
                }
            }
            public override DisposeAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object argument)
            {
                var value = base.VisitFieldReference(operation, argument);

                if (_trackedInstanceFieldLocationsOpt != null &&
                    !operation.Field.IsStatic &&
                    operation.Instance?.Kind == OperationKind.InstanceReference)
                {
                    var pointsToAbstractValue = GetPointsToAbstractValue(operation);
                    if (pointsToAbstractValue.Kind == PointsToAbstractValueKind.KnownLocations &&
                        pointsToAbstractValue.Locations.Count == 1)
                    {
                        var location = pointsToAbstractValue.Locations.Single();
                        if (location.IsAnalysisEntityDefaultLocation)
                        {
                            if (!_trackedInstanceFieldLocationsOpt.TryGetValue(operation.Field, out _))
                            {
                                // First field reference on any control flow path.
                                // Create a default instance to represent the object referenced by the field at start of the method and
                                // check if the instance has NotDisposed state, indicating it is a disposable field that must be tracked.
                                if (HandleInstanceCreation(operation, pointsToAbstractValue, defaultValue: DisposeAbstractValue.NotDisposable) == DisposeAbstractValue.NotDisposed)
                                {
                                    _trackedInstanceFieldLocationsOpt.Add(operation.Field, pointsToAbstractValue);
                                }
                            }
                            else if (!CurrentAnalysisData.ContainsKey(location))
                            {
                                // This field has already started being tracked on a different control flow path.
                                // Process the default instance creation on this control flow path as well.
                                var disposedState = HandleInstanceCreation(operation, pointsToAbstractValue, DisposeAbstractValue.NotDisposable);
                                Debug.Assert(disposedState == DisposeAbstractValue.NotDisposed);
                            }
                        }
                    }
                }

                return(value);
            }
 protected override void ResetCurrentAnalysisData()
 => CurrentAnalysisData.Reset(ValueDomain.UnknownOrMayBeValue);
 protected override ValueContentAbstractValue GetAbstractValue(AnalysisEntity analysisEntity)
 => CurrentAnalysisData.TryGetValue(analysisEntity, out var value) ? value : ValueDomain.UnknownOrMayBeValue;
 protected override void StopTrackingAbstractValue(AbstractLocation location) => CurrentAnalysisData.Remove(location);
 private bool IsNotOrMaybeValidatedLocation(AbstractLocation location) =>
 CurrentAnalysisData.TryGetValue(location, out var value) &&
 (value == ParameterValidationAbstractValue.NotValidated || value == ParameterValidationAbstractValue.MayBeValidated);
 protected override ParameterValidationAbstractValue GetAbstractValue(AbstractLocation location)
 => CurrentAnalysisData.TryGetValue(location, out var value) ? value : ValueDomain.Bottom;
Esempio n. 18
0
 protected override NullAbstractValue GetAbstractValue(ISymbol symbol) =>
 CurrentAnalysisData.TryGetValue(symbol, out var value) ? value : UnknownOrMayBeValue;
Esempio n. 19
0
 protected override bool HasAbstractValue(AnalysisEntity analysisEntity) => CurrentAnalysisData.HasAbstractValue(analysisEntity);
 protected sealed override void StartTrackingPredicatedData(AnalysisEntity predicatedEntity, TAnalysisData?truePredicateData, TAnalysisData?falsePredicateData)
 => CurrentAnalysisData?.StartTrackingPredicatedData(
     predicatedEntity,
     truePredicateData,
     falsePredicateData);
 protected sealed override void StopTrackingPredicatedData(AnalysisEntity predicatedEntity)
 => CurrentAnalysisData?.StopTrackingPredicatedData(predicatedEntity);
 protected sealed override void TransferPredicatedData(AnalysisEntity fromEntity, AnalysisEntity toEntity)
 => CurrentAnalysisData?.TransferPredicatedData(fromEntity, toEntity);
Esempio n. 23
0
 protected override void ResetCurrentAnalysisData() => CurrentAnalysisData.Reset(GetResetValue);
 protected override DisposeAbstractValue GetAbstractValue(AbstractLocation location) => CurrentAnalysisData.TryGetValue(location, out var value) ? value : ValueDomain.UnknownOrMayBeValue;
Esempio n. 25
0
 protected override CopyAbstractValue GetAbstractValue(AnalysisEntity analysisEntity) => CurrentAnalysisData.TryGetValue(analysisEntity, out var value) ? value : CopyAbstractValue.Unknown;
Esempio n. 26
0
            private void SetValueFromPredicate(
                AnalysisEntity key,
                NullAbstractValue value,
                PointsToAnalysisData negatedCurrentAnalysisData,
                bool equals,
                bool inferInCurrentAnalysisData,
                bool inferInNegatedCurrentAnalysisData,
                IOperation target,
                ref PredicateValueKind predicateValueKind)
            {
                // Compute the negated value.
                NullAbstractValue negatedValue = NegatePredicateValue(value);

                // Check if the key already has an existing "Null" or "NotNull" NullState that would make the condition always true or false.
                // If so, set the predicateValueKind to always true/false, set the value in branch that can never be taken to NullAbstractValue.Invalid
                // and turn off value inference in one of the branch.
                if (CurrentAnalysisData.TryGetValue(key, out PointsToAbstractValue existingPointsToValue))
                {
                    NullAbstractValue existingNullValue = existingPointsToValue.NullState;
                    if (IsValidValueForPredicateAnalysis(existingNullValue) &&
                        (existingNullValue == NullAbstractValue.Null || value == NullAbstractValue.Null))
                    {
                        if (value == existingNullValue && equals ||
                            negatedValue == existingNullValue && !equals)
                        {
                            predicateValueKind         = PredicateValueKind.AlwaysTrue;
                            negatedValue               = NullAbstractValue.Invalid;
                            inferInCurrentAnalysisData = false;
                        }

                        if (negatedValue == existingNullValue && equals ||
                            value == existingNullValue && !equals)
                        {
                            predicateValueKind = PredicateValueKind.AlwaysFalse;
                            value = NullAbstractValue.Invalid;
                            inferInNegatedCurrentAnalysisData = false;
                        }
                    }
                }

                // Swap value and negatedValue if we are processing not-equals operator.
                if (!equals)
                {
                    if (value != NullAbstractValue.Invalid && negatedValue != NullAbstractValue.Invalid)
                    {
                        var temp = value;
                        value        = negatedValue;
                        negatedValue = temp;
                    }
                }

                if (inferInCurrentAnalysisData)
                {
                    // Set value for the CurrentAnalysisData.
                    SetAbstractValueFromPredicate(CurrentAnalysisData, key, target, value);
                }

                if (inferInNegatedCurrentAnalysisData)
                {
                    // Set negated value for the NegatedCurrentAnalysisData.
                    SetAbstractValueFromPredicate(negatedCurrentAnalysisData, key, target, negatedValue);
                }
            }