Esempio n. 1
0
        public override MultiValue VisitFieldReference(IFieldReferenceOperation fieldRef, StateValue state)
        {
            var field = fieldRef.Field;

            switch (field.Name)
            {
            case "EmptyTypes" when field.ContainingType.IsTypeOf("System", "Type"): {
                return(ArrayValue.Create(0));
            }

            case "Empty" when field.ContainingType.IsTypeOf("System", "String"): {
                return(new KnownStringValue(string.Empty));
            }
            }

            if (TryGetConstantValue(fieldRef, out var constValue))
            {
                return(constValue);
            }

            if (fieldRef.Field.Type.IsTypeInterestingForDataflow())
            {
                return(new FieldValue(fieldRef.Field));
            }

            return(TopValue);
        }
Esempio n. 2
0
        public override void VisitFieldReference(IFieldReferenceOperation operation)
        {
            var member = operation.Member;
            var field  = operation.Field;

            base.VisitFieldReference(operation);
        }
Esempio n. 3
0
        private static void AssignTo(IOperation target, bool inConstructor, ITypeSymbol staticConstructorType, HashSet <IFieldSymbol> assignedToFields, HashSet <IFieldSymbol> mightBecomeReadOnlyFields)
        {
            if (target.Kind == OperationKind.FieldReference)
            {
                IFieldReferenceOperation fieldReference = (IFieldReferenceOperation)target;
                if (inConstructor && fieldReference.Instance != null)
                {
                    switch (fieldReference.Instance.Kind)
                    {
                    case OperationKind.InstanceReference:
                        return;
                    }
                }

                IFieldSymbol targetField = fieldReference.Field;

                if (staticConstructorType != null && targetField.IsStatic && targetField.ContainingType == staticConstructorType)
                {
                    return;
                }

                assignedToFields.Add(targetField);
                mightBecomeReadOnlyFields.Remove(targetField);

                if (fieldReference.Instance != null && fieldReference.Instance.Type.IsValueType)
                {
                    AssignTo(fieldReference.Instance, inConstructor, staticConstructorType, assignedToFields, mightBecomeReadOnlyFields);
                }
            }
        }
Esempio n. 4
0
 public override bool VisitFieldReference([NotNull] IFieldReferenceOperation operation1,
                                          [CanBeNull] IOperation argument)
 {
     return(argument is IFieldReferenceOperation operation2 && AreBaseOperationsEqual(operation1, operation2) &&
            AreSymbolsEqual(operation1.Field, operation2.Field) &&
            AreSymbolsEqual(operation1.Member, operation2.Member) && operation1.IsDeclaration == operation2.IsDeclaration);
 }
        public static void RegisterMemberAccess(this AnalysisContext context, Action <InvocationAnalysisContext> action)
        {
            var operationKinds = new[]
            {
                OperationKind.Invocation,
                OperationKind.SimpleAssignment,
                OperationKind.VariableDeclaration,
                OperationKind.ObjectCreation,
                OperationKind.FieldInitializer,
                OperationKind.FieldReference,
            };

            context.RegisterOperationAction(ctx =>
            {
                ISymbol?symbol = ctx.Operation switch
                {
                    IInvocationOperation invocation => invocation.TargetMethod,
                    IPropertyReferenceOperation property => property.Property.Type,
                    IObjectCreationOperation creation => creation.Type,
                    ISimpleAssignmentOperation assignment => assignment.Type,
                    IFieldInitializerOperation fieldInitializer => fieldInitializer.Type,
                    IFieldReferenceOperation fieldRef => fieldRef.Type,
                    IVariableDeclarationOperation variableDeclaration => variableDeclaration.Type,
                    _ => null,
                };

                if (symbol is null)
                {
                    return;
                }

                var location = ctx.Operation.Syntax.GetLocation();
                var newCtx   = new InvocationAnalysisContext(symbol, location, ctx.Compilation, ctx.Options, ctx.ReportDiagnostic, ctx.CancellationToken);

                action(newCtx);
            }, operationKinds);

            context.RegisterSymbolAction(ctx =>
            {
                var symbol = ctx.Symbol switch
                {
                    IPropertySymbol property => property.Type,
                    IParameterSymbol parameter => parameter.Type,
                    IMethodSymbol method => method.ReturnsVoid ? null : method.ReturnType,
                    IFieldSymbol field => field.Type,
                    _ => null,
                };

                if (symbol is null)
                {
                    return;
                }

                var location = ctx.Symbol.Locations[0];
                var newCtx   = new InvocationAnalysisContext(symbol, location, ctx.Compilation, ctx.Options, ctx.ReportDiagnostic, ctx.CancellationToken);

                action(newCtx);
            }, SymbolKind.Property, SymbolKind.Method, SymbolKind.Parameter, SymbolKind.Field);
        }
Esempio n. 6
0
        private void ProcessFieldReferenceOperation(IFieldReferenceOperation fieldOp)
        {
            if (fieldOp.Instance == null)
            {
                // Static members are not supported now
                // TODO: Report a warning
                return;
            }

            var referenceModel = this.TryGetVariableFromOperation(fieldOp.Instance) as ReferenceModel;

            if (referenceModel == null)
            {
                // Compute the reference in a separate node if it is not a variable
                referenceModel = (ReferenceModel)this.Context.CreateTemporaryVariableModel(
                    this.Context.ModelManager.TryGetFactory(fieldOp.Instance.Type),
                    fieldOp.Instance.Type);
                var referenceNode = this.Context.PrependCurrentNode(fieldOp.Instance.Syntax, DisplayNodeConfig.Inherit);
                referenceNode.VariableModel = referenceModel;
            }

            var fields = this.Context.ModelManager.TypeContext.GetFieldDefinitions(fieldOp.Field);

            if (this.Context.CurrentNode.VariableModel == null && this.Context.CurrentNode.Operation == null)
            {
                // Start by filling the left side of the assignment, if not filled already
                // (by a variable or an operation)
                this.Context.CurrentNode.Operation = new HeapOperation(
                    SpecialOperationKind.FieldWrite,
                    referenceModel,
                    fields);
            }
            else
            {
                Contract.Assert(this.Context.CurrentNode.ValueModel == null);

                // Otherwise, fill the right side of the assignment
                var readOp = new HeapOperation(SpecialOperationKind.FieldRead, referenceModel, fields);

                if (this.Context.CurrentNode.Operation == null)
                {
                    this.Context.CurrentNode.Operation = readOp;
                }
                else
                {
                    // If there is already an operation (such as field write), put the read to a new node
                    var readResult = this.Context.CreateTemporaryVariableModel(
                        this.Context.ModelManager.TryGetFactory(fieldOp.Type),
                        fieldOp.Type);
                    var readNode = this.Context.PrependCurrentNode(
                        fieldOp.Syntax,
                        DisplayNodeConfig.Inherit,
                        isFinal: true);
                    readNode.VariableModel = readResult;
                    readNode.Operation     = readOp;
                    this.Context.CurrentNode.ValueModel = readResult;
                }
            }
        }
Esempio n. 7
0
        public override void VisitFieldReference(IFieldReferenceOperation operation)
        {
            Assert.Equal(OperationKind.FieldReference, operation.Kind);
            VisitMemberReference(operation);

            Assert.Same(operation.Member, operation.Field);
            var isDeclaration = operation.IsDeclaration;
        }
Esempio n. 8
0
        private static AbstractExpression ReadFieldReference(IFieldReferenceOperation op)
        {
            var context = CodeReaderContext.GetContextOrThrow();

            return(new MemberExpression {
                Target = ReadExpression(op.Instance),
                Member = context.FindMemberOrThrow <FieldMember>(op.Field)
            });
        }
            public override ValueContentAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object argument)
            {
                var value = base.VisitFieldReference(operation, argument);

                // Handle "string.Empty"
                if (operation.Field.Name.Equals("Empty", StringComparison.Ordinal) &&
                    operation.Field.ContainingType.SpecialType == SpecialType.System_String)
                {
                    return(ValueContentAbstractValue.ContainsEmptyStringLiteralState);
                }

                return(value);
            }
Esempio n. 10
0
        public override MultiValue VisitFieldReference(IFieldReferenceOperation fieldRef, StateValue state)
        {
            if (fieldRef.Field.Type.IsTypeInterestingForDataflow())
            {
                var field = fieldRef.Field;
                if (field.Name is "Empty" && field.ContainingType.HasName("System.String"))
                {
                    return(new KnownStringValue(string.Empty));
                }

                return(new FieldValue(fieldRef.Field));
            }

            return(TopValue);
        }
Esempio n. 11
0
        private void AnalyzeOperation(OperationAnalysisContext context)
        {
            var symbol = context.Operation switch
            {
                IObjectCreationOperation creation => creation.Constructor,
                IInvocationOperation invocation => invocation.TargetMethod,
                IFieldReferenceOperation field => field.Member,
                IMethodReferenceOperation method => method.Member,
                IPropertyReferenceOperation property => property.Member,
                IEventReferenceOperation @event => @event.Member,
                _ => throw new InvalidOperationException("Unexpected operation kind: " + context.Operation.Kind),
            };

            VisitOperationSymbol(context, symbol);
        }
        private static void AssignTo(IOperation target, HashSet <ILocalSymbol> assignedToLocals, HashSet <ILocalSymbol> mightBecomeConstLocals)
        {
            if (target.Kind == OperationKind.LocalReference)
            {
                ILocalSymbol targetLocal = ((ILocalReferenceOperation)target).Local;

                assignedToLocals.Add(targetLocal);
                mightBecomeConstLocals.Remove(targetLocal);
            }
            else if (target.Kind == OperationKind.FieldReference)
            {
                IFieldReferenceOperation fieldReference = (IFieldReferenceOperation)target;
                if (fieldReference.Instance != null && fieldReference.Instance.Type.IsValueType)
                {
                    AssignTo(fieldReference.Instance, assignedToLocals, mightBecomeConstLocals);
                }
            }
        }
Esempio n. 13
0
        private ISymbol?GetUnoSymbolFromOperation(IOperation operation)
        {
            ISymbol symbol = operation switch
            {
                IInvocationOperation invocationOperation => invocationOperation.TargetMethod,
                IObjectCreationOperation objectCreation => objectCreation.Type,
                IFieldReferenceOperation fieldReferenceOperation => fieldReferenceOperation.Field,
                IPropertyReferenceOperation propertyReferenceOperation => propertyReferenceOperation.Property,
                    _ => throw new InvalidOperationException("This code path is unreachable.")
            };


            if (IsUnoSymbol(symbol))
            {
                return(symbol);
            }

            return(null);
        }
        private static void AnalyzeAccess(OperationAnalysisContext context)
        {
            IFieldReferenceOperation fieldReference = (IFieldReferenceOperation)context.Operation;

            if (fieldReference.Instance == null)
            {
                //static method, don't care
                return;
            }

            IFieldSymbol     field           = fieldReference.Field;
            INamedTypeSymbol namedTypeSymbol = field.ContainingType;

            if (!namedTypeSymbol.IsTupleType)
            {
                return;
            }


            if (!SymbolEqualityComparer.Default.Equals(field.CorrespondingTupleField, field))
            {
                // they are not using the Item1, Item2, Item3, etc.
                return;
            }

            // they are using Item1/Item2/ etc.  Detect if that field has a name they can use instead.
            foreach (var element in namedTypeSymbol.TupleElements)
            {
                if (!SymbolEqualityComparer.Default.Equals(element.CorrespondingTupleField, field))
                {
                    continue;
                }

                if (element.Name == element.CorrespondingTupleField.Name)
                {
                    continue;
                }

                context.ReportDiagnostic(Diagnostic.Create(Rule, fieldReference.Syntax.GetLocation(), element.Name, field.Name));
            }
        }
            private Task VisitReferenceAsync(IOperation operation, CancellationToken cancellationToken)
            {
                Debug.Assert(operation is
                             ILocalReferenceOperation or
                             IParameterReferenceOperation or
                             IFieldReferenceOperation or
                             IPropertyReferenceOperation);

                if (IsContainedIn <IArgumentOperation>(operation, out var argumentOperation) && argumentOperation.Parameter is not null)
                {
                    if (argumentOperation.Parameter.IsRefOrOut())
                    {
                        // Always add ref or out parameters to track as assignments since the values count as
                        // assignments across method calls for the purposes of value tracking.
                        return(AddOperationAsync(operation, argumentOperation.Parameter, cancellationToken));
                    }

                    // If the parameter is not a ref or out param, track the reference assignments that count
                    // as input to the argument being passed to the method.
                    return(AddReference(operation, cancellationToken));
                }

                if (IsContainedIn <IReturnOperation>(operation) || IsContainedIn <IAssignmentOperation>(operation))
                {
                    // If the reference is part of a return operation or assignment operation we want to track where the values come from
                    // since they contribute to the "output" of the method/assignment and are relavent for value tracking.
                    return(AddReference(operation, cancellationToken));
                }

                return(Task.CompletedTask);

                Task AddReference(IOperation operation, CancellationToken cancellationToken)
                => operation switch
                {
                    IParameterReferenceOperation parameterReference => AddOperationAsync(operation, parameterReference.Parameter, cancellationToken),
                    IFieldReferenceOperation fieldReferenceOperation => AddOperationAsync(operation, fieldReferenceOperation.Member, cancellationToken),
                    IPropertyReferenceOperation propertyReferenceOperation => AddOperationAsync(operation, propertyReferenceOperation.Member, cancellationToken),
                    ILocalReferenceOperation localReferenceOperation => AddOperationAsync(operation, localReferenceOperation.Local, cancellationToken),
                    _ => Task.CompletedTask
                };
            }
        public sealed override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                INamedTypeSymbol?cipherModeTypeSymbol =
                    compilationStartAnalysisContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemSecurityCryptographyCipherMode);

                if (cipherModeTypeSymbol == null)
                {
                    return;
                }

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    IFieldReferenceOperation fieldReferenceOperation =
                        (IFieldReferenceOperation)operationAnalysisContext.Operation;
                    IFieldSymbol fieldSymbol = fieldReferenceOperation.Field;

                    if (Equals(fieldSymbol.ContainingType, cipherModeTypeSymbol) &&
                        UnsafeCipherModes.Contains(fieldSymbol.MetadataName))
                    {
                        operationAnalysisContext.ReportDiagnostic(
                            Diagnostic.Create(
                                Rule,
                                fieldReferenceOperation.Syntax.GetLocation(),
                                fieldSymbol.MetadataName));
                    }
                },
                    OperationKind.FieldReference);
            });
        }
            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);
            }
Esempio n. 18
0
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="operation">IOperationインスタンス</param>
        /// <param name="container">イベントコンテナ</param>
        public FieldReference(IFieldReferenceOperation operation, EventContainer container) : base(container)
        {
            if (operation.Field.IsStatic)
            {
                var name = $"{operation.Field.ContainingSymbol}".Replace($"{operation.Field.ContainingNamespace}.", string.Empty, StringComparison.CurrentCulture);
                Expressions.Add(new Expression(name,
                                               Expression.GetSymbolTypeName(operation.Field.ContainingSymbol)));
                Expressions.Add(new Expression(".", string.Empty));

                // 外部参照チェック
                if (operation.Field.ContainingSymbol is INamedTypeSymbol)
                {
                    // 外部ファイル参照イベント発行
                    RaiseOtherFileReferenced(operation.Syntax, operation.Field.ContainingSymbol);
                }
            }
            else
            {
                Expressions.Add(new Expression("this", Expression.GetSymbolTypeName(operation.Field)));
                Expressions.Add(new Expression(".", string.Empty));
            }
            Expressions.Add(new Expression(operation.Field.Name, Expression.GetSymbolTypeName(operation.Field.Type)));
        }
Esempio n. 19
0
 public virtual void VisitFieldReference(IFieldReferenceOperation operation)
 {
     DefaultVisit(operation);
 }
Esempio n. 20
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

            // Security analyzer - analyze and report diagnostics on generated code.
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemSecurityAuthenticationSslProtocols,
                        out INamedTypeSymbol? sslProtocolsSymbol))
                {
                    return;
                }

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    IFieldReferenceOperation fieldReferenceOperation = (IFieldReferenceOperation)operationAnalysisContext.Operation;
                    if (IsReferencingSslProtocols(
                            fieldReferenceOperation,
                            out bool isDeprecatedProtocol,
                            out bool isHardcodedOkayProtocol))
                    {
                        if (isDeprecatedProtocol)
                        {
                            operationAnalysisContext.ReportDiagnostic(
                                fieldReferenceOperation.CreateDiagnostic(
                                    DeprecatedRule,
                                    fieldReferenceOperation.Field.Name));
                        }
                        else if (isHardcodedOkayProtocol)
                        {
                            operationAnalysisContext.ReportDiagnostic(
                                fieldReferenceOperation.CreateDiagnostic(
                                    HardcodedRule,
                                    fieldReferenceOperation.Field.Name));
                        }
                    }
                },
                    OperationKind.FieldReference);

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    IOperation?valueOperation;
                    switch (operationAnalysisContext.Operation)
                    {
                    case IAssignmentOperation assignmentOperation:
                        // Make sure this is an assignment operation for a SslProtocols value.
                        if (!sslProtocolsSymbol.Equals(assignmentOperation.Target.Type))
                        {
                            return;
                        }

                        valueOperation = assignmentOperation.Value;
                        break;

                    case IArgumentOperation argumentOperation:
                        if (!sslProtocolsSymbol.Equals(argumentOperation.Type))
                        {
                            return;
                        }

                        valueOperation = argumentOperation.Value;
                        break;

                    case IReturnOperation returnOperation:
                        if (returnOperation.ReturnedValue == null ||
                            !sslProtocolsSymbol.Equals(returnOperation.ReturnedValue.Type))
                        {
                            return;
                        }

                        valueOperation = returnOperation.ReturnedValue;
                        break;

                    case IVariableInitializerOperation variableInitializerOperation:
                        if (variableInitializerOperation.Value == null ||
                            !sslProtocolsSymbol.Equals(variableInitializerOperation.Value.Type))
                        {
                            return;
                        }

                        valueOperation = variableInitializerOperation.Value;
                        break;

                    default:
                        Debug.Fail("Unhandled IOperation " + operationAnalysisContext.Operation.Kind);
                        return;
                    }

                    // Find the topmost operation with a bad bit set, unless we find an operation that would've been
                    // flagged by the FieldReference callback above.
                    IOperation?foundDeprecatedOperation = null;
                    bool foundDeprecatedReference       = false;
                    IOperation?foundHardcodedOperation  = null;
                    bool foundHardcodedReference        = false;
                    foreach (IOperation childOperation in valueOperation.DescendantsAndSelf())
                    {
                        if (childOperation is IFieldReferenceOperation fieldReferenceOperation &&
                            IsReferencingSslProtocols(
                                fieldReferenceOperation,
                                out var isDeprecatedProtocol,
                                out var isHardcodedOkayProtocol))
                        {
                            if (isDeprecatedProtocol)
                            {
                                foundDeprecatedReference = true;
                            }
                            else if (isHardcodedOkayProtocol)
                            {
                                foundHardcodedReference = true;
                            }

                            if (foundDeprecatedReference && foundHardcodedReference)
                            {
                                return;
                            }
                        }

                        if (childOperation.ConstantValue.HasValue &&
                            childOperation.ConstantValue.Value is int integerValue)
                        {
                            if (foundDeprecatedOperation == null &&         // Only want the first.
                                (integerValue & UnsafeBits) != 0)
                            {
                                foundDeprecatedOperation = childOperation;
                            }

                            if (foundHardcodedOperation == null &&         // Only want the first.
                                (integerValue & HardcodedBits) != 0)
                            {
                                foundHardcodedOperation = childOperation;
                            }
                        }
                    }

                    if (foundDeprecatedOperation != null && !foundDeprecatedReference)
                    {
                        operationAnalysisContext.ReportDiagnostic(
                            foundDeprecatedOperation.CreateDiagnostic(
                                DeprecatedRule,
                                foundDeprecatedOperation.ConstantValue));
                    }

                    if (foundHardcodedOperation != null && !foundHardcodedReference)
                    {
                        operationAnalysisContext.ReportDiagnostic(
                            foundHardcodedOperation.CreateDiagnostic(
                                HardcodedRule,
                                foundHardcodedOperation.ConstantValue));
                    }
                },
                    OperationKind.SimpleAssignment,
                    OperationKind.CompoundAssignment,
                    OperationKind.Argument,
                    OperationKind.Return,
                    OperationKind.VariableInitializer);

                return;

                // Local function(s).
                bool IsReferencingSslProtocols(
                    IFieldReferenceOperation fieldReferenceOperation,
                    out bool isDeprecatedProtocol,
                    out bool isHardcodedOkayProtocol)
                {
                    RoslynDebug.Assert(sslProtocolsSymbol != null);

                    if (sslProtocolsSymbol.Equals(fieldReferenceOperation.Field.ContainingType))
                    {
                        if (HardcodedSslProtocolsMetadataNames.Contains(fieldReferenceOperation.Field.Name))
                        {
                            isHardcodedOkayProtocol = true;
                            isDeprecatedProtocol    = false;
                        }
                        else if (fieldReferenceOperation.Field.Name == "None")
                        {
                            isHardcodedOkayProtocol = false;
                            isDeprecatedProtocol    = false;
                        }
                        else
                        {
                            isDeprecatedProtocol    = true;
                            isHardcodedOkayProtocol = false;
                        }

                        return(true);
                    }
                    else
                    {
                        isHardcodedOkayProtocol = false;
                        isDeprecatedProtocol    = false;
                        return(false);
                    }
                }
            });
        }
Esempio n. 21
0
        public override void Initialize(AnalysisContext context)
        {
            if (!Debugger.IsAttached) // prefer single thread for debugging in development
            {
                context.EnableConcurrentExecution();
            }

            if (context.IsAuditMode())
            {
                context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
            }
            else
            {
                context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            }

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationContext) =>
            {
                var config = Configuration.GetOrCreate(compilationContext);

                if (config.AuditMode)
                {
                    TaintedDataSymbolMap <SinkInfo> sinkInfoSymbolMap = config.TaintConfiguration.GetSinkSymbolMap(this.SinkKind);
                    if (sinkInfoSymbolMap.IsEmpty)
                    {
                        return;
                    }

                    Compilation compilation = compilationContext.Compilation;
                    compilationContext.RegisterOperationBlockStartAction(
                        operationBlockStartContext =>
                    {
                        ISymbol owningSymbol                = operationBlockStartContext.OwningSymbol;
                        AnalyzerOptions options             = operationBlockStartContext.Options;
                        CancellationToken cancellationToken = operationBlockStartContext.CancellationToken;
                        if (options.IsConfiguredToSkipAnalysis(TaintedDataEnteringSinkDescriptor, owningSymbol, compilation, cancellationToken))
                        {
                            return;
                        }

                        WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation);

                        void CreateWarning(OperationAnalysisContext operationAnalysisContext, Location location, ISymbol paramSymbol, ISymbol symbol)
                        {
                            // Something like:
                            // CA3001: Potential SQL injection vulnerability was found where '{0}' in method '{1}' may be tainted by user-controlled data from '{2}' in method '{3}'.
                            Diagnostic diagnostic = Diagnostic.Create(
                                this.TaintedDataEnteringSinkDescriptor,
                                location,
                                additionalLocations: new Location[] { location },
                                messageArgs: new object[] {
                                paramSymbol.Name,
                                symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)
                            });
                            operationAnalysisContext.ReportDiagnostic(diagnostic);
                        }

                        bool IsConstant(IOperation operation, IOperation value, OperationAnalysisContext operationAnalysisContext)
                        {
                            if (value.ConstantValue.HasValue || value is ITypeOfOperation)
                            {
                                return(true);
                            }

                            if (!operation.TryGetEnclosingControlFlowGraph(out var cfg))
                            {
                                return(false);
                            }

                            var valueContentResult = ValueContentAnalysis.TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider,
                                                                                                operationAnalysisContext.Options, TaintedDataEnteringSinkDescriptor, PointsToAnalysisKind.Complete, operationAnalysisContext.CancellationToken);
                            if (valueContentResult == null)
                            {
                                return(false);
                            }

                            ValueContentAbstractValue abstractValue = valueContentResult[value.Kind, value.Syntax];
                            return(abstractValue.NonLiteralState == ValueContainsNonLiteralState.No);
                        }

                        operationBlockStartContext.RegisterOperationAction(
                            operationAnalysisContext =>
                        {
                            IAssignmentOperation operation = (IAssignmentOperation)operationAnalysisContext.Operation;
                            if (!(operation.Target is IPropertyReferenceOperation propertyReferenceOperation))
                            {
                                return;
                            }

                            IEnumerable <SinkInfo>?infosForType = sinkInfoSymbolMap.GetInfosForType(propertyReferenceOperation.Member.ContainingType);
                            if (infosForType != null &&
                                infosForType.Any(x => x.SinkProperties.Contains(propertyReferenceOperation.Member.MetadataName)) &&
                                !IsConstant(operation, operation.Value, operationAnalysisContext))
                            {
                                CreateWarning(
                                    operationAnalysisContext,
                                    propertyReferenceOperation.Syntax.GetLocation(),
                                    operation.Value.Type,
                                    propertyReferenceOperation.Member);
                            }
                        },
                            OperationKind.SimpleAssignment);

                        operationBlockStartContext.RegisterOperationAction(
                            operationAnalysisContext =>
                        {
                            IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation;
                            IEnumerable <SinkInfo>?infosForType      = sinkInfoSymbolMap.GetInfosForType(invocationOperation.TargetMethod.ContainingType);
                            if (infosForType == null)
                            {
                                return;
                            }

                            foreach (SinkInfo sinkInfo in infosForType)
                            {
                                foreach (IArgumentOperation taintedArgument in invocationOperation.Arguments.Where(x => !IsConstant(x, x.Value, operationAnalysisContext)))
                                {
                                    if (sinkInfo.SinkMethodParameters.TryGetValue(invocationOperation.TargetMethod.MetadataName, out ImmutableHashSet <string> sinkParameters) &&
                                        sinkParameters.Contains(taintedArgument.Parameter.MetadataName))
                                    {
                                        CreateWarning(operationAnalysisContext, invocationOperation.Syntax.GetLocation(), taintedArgument.Parameter, invocationOperation.TargetMethod);
                                        return;
                                    }
                                }
                            }
                        },
                            OperationKind.Invocation);

                        operationBlockStartContext.RegisterOperationAction(
                            operationAnalysisContext =>
                        {
                            IObjectCreationOperation invocationOperation = (IObjectCreationOperation)operationAnalysisContext.Operation;
                            IEnumerable <SinkInfo>?infosForType          = sinkInfoSymbolMap.GetInfosForType(invocationOperation.Constructor.ContainingType);
                            if (infosForType == null)
                            {
                                return;
                            }

                            foreach (SinkInfo sinkInfo in infosForType)
                            {
                                foreach (IArgumentOperation taintedArgument in invocationOperation.Arguments.Where(x => !IsConstant(x, x.Value, operationAnalysisContext)))
                                {
                                    if (sinkInfo.IsAnyStringParameterInConstructorASink &&
                                        taintedArgument.Parameter.Type.SpecialType == SpecialType.System_String)
                                    {
                                        CreateWarning(operationAnalysisContext, invocationOperation.Syntax.GetLocation(), taintedArgument.Parameter, invocationOperation.Constructor);
                                        return;
                                    }
                                    else if (sinkInfo.SinkMethodParameters.TryGetValue(invocationOperation.Constructor.MetadataName, out ImmutableHashSet <string> sinkParameters) &&
                                             sinkParameters.Contains(taintedArgument.Parameter.MetadataName))
                                    {
                                        CreateWarning(operationAnalysisContext, invocationOperation.Syntax.GetLocation(), taintedArgument.Parameter, invocationOperation.Constructor);
                                        return;
                                    }
                                }
                            }
                        },
                            OperationKind.ObjectCreation);
                    });
                }
                else
                {
                    TaintedDataSymbolMap <SourceInfo> sourceInfoSymbolMap = config.TaintConfiguration.GetSourceSymbolMap(this.SinkKind);
                    if (sourceInfoSymbolMap.IsEmpty)
                    {
                        return;
                    }

                    TaintedDataSymbolMap <SinkInfo> sinkInfoSymbolMap = config.TaintConfiguration.GetSinkSymbolMap(this.SinkKind);
                    if (sinkInfoSymbolMap.IsEmpty)
                    {
                        return;
                    }

                    Compilation compilation = compilationContext.Compilation;
                    compilationContext.RegisterOperationBlockStartAction(
                        operationBlockStartContext =>
                    {
                        ISymbol owningSymbol                = operationBlockStartContext.OwningSymbol;
                        AnalyzerOptions options             = operationBlockStartContext.Options;
                        CancellationToken cancellationToken = operationBlockStartContext.CancellationToken;
                        if (options.IsConfiguredToSkipAnalysis(TaintedDataEnteringSinkDescriptor, owningSymbol, compilation, cancellationToken))
                        {
                            return;
                        }

                        WellKnownTypeProvider wellKnownTypeProvider      = WellKnownTypeProvider.GetOrCreate(compilation);
                        Lazy <ControlFlowGraph?> controlFlowGraphFactory = new Lazy <ControlFlowGraph?>(
                            () => operationBlockStartContext.OperationBlocks.GetControlFlowGraph());
                        Lazy <PointsToAnalysisResult?> pointsToFactory = new Lazy <PointsToAnalysisResult?>(
                            () =>
                        {
                            if (controlFlowGraphFactory.Value == null)
                            {
                                return(null);
                            }

                            InterproceduralAnalysisConfiguration interproceduralAnalysisConfiguration = InterproceduralAnalysisConfiguration.Create(
                                options,
                                SupportedDiagnostics,
                                controlFlowGraphFactory.Value,
                                operationBlockStartContext.Compilation,
                                defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive,
                                cancellationToken: cancellationToken,
                                defaultMaxInterproceduralMethodCallChain: config.MaxInterproceduralMethodCallChain,
                                defaultMaxInterproceduralLambdaOrLocalFunctionCallChain: config.MaxInterproceduralLambdaOrLocalFunctionCallChain);
                            return(PointsToAnalysis.TryGetOrComputeResult(
                                       controlFlowGraphFactory.Value,
                                       owningSymbol,
                                       options,
                                       wellKnownTypeProvider,
                                       PointsToAnalysisKind.Complete,
                                       interproceduralAnalysisConfiguration,
                                       interproceduralAnalysisPredicate: null));
                        });
                        Lazy <(PointsToAnalysisResult?, ValueContentAnalysisResult?)> valueContentFactory = new Lazy <(PointsToAnalysisResult?, ValueContentAnalysisResult?)>(
                            () =>
                        {
                            if (controlFlowGraphFactory.Value == null)
                            {
                                return(null, null);
                            }

                            InterproceduralAnalysisConfiguration interproceduralAnalysisConfiguration = InterproceduralAnalysisConfiguration.Create(
                                options,
                                SupportedDiagnostics,
                                controlFlowGraphFactory.Value,
                                operationBlockStartContext.Compilation,
                                defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive,
                                cancellationToken: cancellationToken,
                                defaultMaxInterproceduralMethodCallChain: config.MaxInterproceduralMethodCallChain,
                                defaultMaxInterproceduralLambdaOrLocalFunctionCallChain: config.MaxInterproceduralLambdaOrLocalFunctionCallChain);
                            ValueContentAnalysisResult?valuecontentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult(
                                controlFlowGraphFactory.Value,
                                owningSymbol,
                                options,
                                wellKnownTypeProvider,
                                PointsToAnalysisKind.Complete,
                                interproceduralAnalysisConfiguration,
                                out _,
                                out PointsToAnalysisResult? p);

                            return(p, valuecontentAnalysisResult);
                        });

                        var rootOperationsNeedingAnalysis = PooledHashSet <IOperation> .GetInstance();

                        operationBlockStartContext.RegisterOperationAction(
                            operationAnalysisContext =>
                        {
                            IPropertyReferenceOperation propertyReferenceOperation = (IPropertyReferenceOperation)operationAnalysisContext.Operation;
                            if (sourceInfoSymbolMap.IsSourceProperty(propertyReferenceOperation.Property))
                            {
                                lock (rootOperationsNeedingAnalysis)
                                {
                                    rootOperationsNeedingAnalysis.Add(propertyReferenceOperation.GetRoot());
                                }
                            }
                        },
                            OperationKind.PropertyReference);

                        if (sourceInfoSymbolMap.RequiresFieldReferenceAnalysis)
                        {
                            operationBlockStartContext.RegisterOperationAction(
                                operationAnalysisContext =>
                            {
                                IFieldReferenceOperation fieldReferenceOperation = (IFieldReferenceOperation)operationAnalysisContext.Operation;
                                if (sourceInfoSymbolMap.IsSourceField(fieldReferenceOperation.Field))
                                {
                                    lock (rootOperationsNeedingAnalysis)
                                    {
                                        rootOperationsNeedingAnalysis.Add(fieldReferenceOperation.GetRoot());
                                    }
                                }
                            },
                                OperationKind.FieldReference);
                        }

                        if (sourceInfoSymbolMap.RequiresParameterReferenceAnalysis)
                        {
                            operationBlockStartContext.RegisterOperationAction(
                                operationAnalysisContext =>
                            {
                                IParameterReferenceOperation parameterReferenceOperation = (IParameterReferenceOperation)operationAnalysisContext.Operation;
                                if (sourceInfoSymbolMap.IsSourceParameter(parameterReferenceOperation.Parameter, wellKnownTypeProvider))
                                {
                                    lock (rootOperationsNeedingAnalysis)
                                    {
                                        rootOperationsNeedingAnalysis.Add(parameterReferenceOperation.GetRoot());
                                    }
                                }
                            },
                                OperationKind.ParameterReference);
                        }

                        operationBlockStartContext.RegisterOperationAction(
                            operationAnalysisContext =>
                        {
                            IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation;
                            if (sourceInfoSymbolMap.IsSourceMethod(
                                    invocationOperation.TargetMethod,
                                    invocationOperation.Arguments,
                                    pointsToFactory,
                                    valueContentFactory,
                                    out _))
                            {
                                lock (rootOperationsNeedingAnalysis)
                                {
                                    rootOperationsNeedingAnalysis.Add(invocationOperation.GetRoot());
                                }
                            }
                        },
                            OperationKind.Invocation);

                        if (config.TaintConfiguration.HasTaintArraySource(SinkKind, config))
                        {
                            operationBlockStartContext.RegisterOperationAction(
                                operationAnalysisContext =>
                            {
                                IArrayInitializerOperation arrayInitializerOperation = (IArrayInitializerOperation)operationAnalysisContext.Operation;
                                if (arrayInitializerOperation.GetAncestor <IArrayCreationOperation>(OperationKind.ArrayCreation)?.Type is IArrayTypeSymbol arrayTypeSymbol &&
                                    sourceInfoSymbolMap.IsSourceConstantArrayOfType(arrayTypeSymbol, arrayInitializerOperation))
                                {
                                    lock (rootOperationsNeedingAnalysis)
                                    {
                                        rootOperationsNeedingAnalysis.Add(operationAnalysisContext.Operation.GetRoot());
                                    }
                                }
                            },
                                OperationKind.ArrayInitializer);
                        }

                        operationBlockStartContext.RegisterOperationBlockEndAction(
                            operationBlockAnalysisContext =>
                        {
                            try
                            {
                                lock (rootOperationsNeedingAnalysis)
                                {
                                    if (!rootOperationsNeedingAnalysis.Any())
                                    {
                                        return;
                                    }

                                    if (controlFlowGraphFactory.Value == null)
                                    {
                                        return;
                                    }

                                    foreach (IOperation rootOperation in rootOperationsNeedingAnalysis)
                                    {
                                        TaintedDataAnalysisResult?taintedDataAnalysisResult = TaintedDataAnalysis.TryGetOrComputeResult(
                                            controlFlowGraphFactory.Value,
                                            operationBlockAnalysisContext.Compilation,
                                            operationBlockAnalysisContext.OwningSymbol,
                                            operationBlockAnalysisContext.Options,
                                            TaintedDataEnteringSinkDescriptor,
                                            sourceInfoSymbolMap,
                                            config.TaintConfiguration.GetSanitizerSymbolMap(this.SinkKind),
                                            sinkInfoSymbolMap,
                                            operationBlockAnalysisContext.CancellationToken,
                                            config.MaxInterproceduralMethodCallChain,
                                            config.MaxInterproceduralLambdaOrLocalFunctionCallChain);
                                        if (taintedDataAnalysisResult == null)
                                        {
                                            return;
                                        }

                                        foreach (TaintedDataSourceSink sourceSink in taintedDataAnalysisResult.TaintedDataSourceSinks)
                                        {
                                            if (!sourceSink.SinkKinds.Contains(this.SinkKind))
                                            {
                                                continue;
                                            }

                                            foreach (SymbolAccess sourceOrigin in sourceSink.SourceOrigins)
                                            {
                                                // Something like:
                                                // CA3001: Potential SQL injection vulnerability was found where '{0}' in method '{1}' may be tainted by user-controlled data from '{2}' in method '{3}'.
                                                Diagnostic diagnostic = Diagnostic.Create(
                                                    this.TaintedDataEnteringSinkDescriptor,
                                                    sourceSink.Sink.Location,
                                                    additionalLocations: new Location[] { sourceOrigin.Location },
                                                    messageArgs: new object[] {
                                                    sourceSink.Sink.Symbol.Name,
                                                    sourceSink.Sink.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                                    sourceOrigin.Symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                                    sourceOrigin.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)
                                                });
                                                operationBlockAnalysisContext.ReportDiagnostic(diagnostic);
                                            }
                                        }
                                    }
                                }
                            }
                            finally
                            {
                                rootOperationsNeedingAnalysis.Free(compilationContext.CancellationToken);
                            }
                        });
                    });
                }
            });
        }
        public override TAbstractAnalysisValue VisitFieldReference(IFieldReferenceOperation operation, object argument)
        {
            var value = base.VisitFieldReference(operation, argument);

            return(ComputeAnalysisValueForReferenceOperation(operation, value));
        }
 public override IdentifierInfo VisitFieldReference([NotNull] IFieldReferenceOperation operation,
                                                    [CanBeNull] object argument)
 {
     return(CreateForMemberReferenceExpression(operation, operation.Field.Type));
 }
 private static bool IsRunContinuationsAsynchronously(IFieldReferenceOperation fieldReference)
 => fieldReference.Member.Name == "RunContinuationsAsynchronously";
        public static bool IsExpressionEqualsDtdProcessingParse(IOperation operation)
        {
            IFieldReferenceOperation enumRef = operation as IFieldReferenceOperation;

            return(enumRef != null && enumRef.HasConstantValue(2)); // DtdProcessing.Parse
        }
Esempio n. 26
0
        public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.ReportDiagnostics);
            analysisContext.EnableConcurrentExecution();

            analysisContext.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.NewtonsoftJsonTypeNameHandling,
                        out INamedTypeSymbol? typeNameHandlingSymbol))
                {
                    return;
                }

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    IFieldReferenceOperation fieldReferenceOperation =
                        (IFieldReferenceOperation)operationAnalysisContext.Operation;
                    if (IsOtherThanNone(fieldReferenceOperation))
                    {
                        operationAnalysisContext.ReportDiagnostic(
                            fieldReferenceOperation.CreateDiagnostic(Rule));
                    }
                },
                    OperationKind.FieldReference);

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    IAssignmentOperation assignmentOperation = (IAssignmentOperation)operationAnalysisContext.Operation;
                    if (!typeNameHandlingSymbol.Equals(assignmentOperation.Target.Type))
                    {
                        return;
                    }

                    // Find the topmost operation with non-zero (not None), unless we find an operation that would've
                    // been flagged by the FieldReference callback above.
                    foreach (IOperation childOperation in assignmentOperation.Value.DescendantsAndSelf())
                    {
                        if (childOperation is IFieldReferenceOperation fieldReferenceOperation &&
                            IsOtherThanNone(fieldReferenceOperation))
                        {
                            return;
                        }

                        if (childOperation.ConstantValue.HasValue &&
                            childOperation.ConstantValue.Value is int integerValue &&
                            integerValue != 0)
                        {
                            operationAnalysisContext.ReportDiagnostic(childOperation.CreateDiagnostic(Rule));
                            return;
                        }
                    }
                },
                    OperationKind.SimpleAssignment,
                    OperationKind.CompoundAssignment);

                return;

                bool IsOtherThanNone(IFieldReferenceOperation fieldReferenceOperation)
                {
                    RoslynDebug.Assert(typeNameHandlingSymbol != null);
                    if (!typeNameHandlingSymbol.Equals(fieldReferenceOperation.Field.ContainingType))
                    {
                        return(false);
                    }

                    return(fieldReferenceOperation.Field.Name != "None");
                };
            });
        }
            public override NullAbstractValue VisitFieldReference(IFieldReferenceOperation operation, object argument)
            {
                var _ = base.VisitFieldReference(operation, argument);

                return(GetValueBasedOnInstanceOrReferenceValue(operation.Instance));
            }
Esempio n. 28
0
 public override IOperation VisitFieldReference(IFieldReferenceOperation operation, object argument)
 {
     return(new FieldReferenceExpression(operation.Field, operation.IsDeclaration, Visit(operation.Instance), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit));
 }
Esempio n. 29
0
 public override void VisitFieldReference([NotNull] IFieldReferenceOperation operation)
 {
     base.VisitFieldReference(operation);
 }
 public override GlobalFlowStateAnalysisValueSet VisitFieldReference(IFieldReferenceOperation operation, object?argument)
 {
     return(GetValueOrDefault(base.VisitFieldReference(operation, argument)));
 }