public override void VisitPropertyReference(IPropertyReferenceOperation operation) { var member = operation.Member; var property = operation.Property; base.VisitPropertyReference(operation); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationStartContext => { Compilation compilation = compilationStartContext.Compilation; INamedTypeSymbol dateTimeType = compilation.GetTypeByMetadataName("System.DateTimeOffset"); compilationStartContext.RegisterOperationAction( operationContext => { IPropertyReferenceOperation invocation = (IPropertyReferenceOperation)operationContext.Operation; if (invocation.Member == null || invocation.Member.ContainingType != dateTimeType) { return; } IPropertySymbol targetProperty = invocation.Property; if (targetProperty == null || !PropertyNames.Contains(targetProperty.MetadataName)) { return; } operationContext.ReportDiagnostic(Diagnostic.Create( rule, invocation.Syntax.GetLocation(), invocation.Member.ContainingType.Name, targetProperty.Name)); }, OperationKind.PropertyReference); }); }
/// <summary> /// Determines if a property is a sink. /// </summary> /// <param name="propertyReferenceOperation">Property to check if it's a sink.</param> /// <param name="sinkKinds">If the property is a sink, <see cref="HashSet{SinkInfo}"/> containing the kinds of sinks; null otherwise.</param> /// <returns>True if the property is a sink, false otherwise.</returns> private bool IsPropertyASink(IPropertyReferenceOperation propertyReferenceOperation, out HashSet <SinkKind> sinkKinds) { Lazy <HashSet <SinkKind> > lazySinkKinds = new Lazy <HashSet <SinkKind> >(() => new HashSet <SinkKind>()); foreach (SinkInfo sinkInfo in this.DataFlowAnalysisContext.SinkInfos.GetInfosForType(propertyReferenceOperation.Member.ContainingType)) { if (lazySinkKinds.IsValueCreated && lazySinkKinds.Value.IsSupersetOf(sinkInfo.SinkKinds)) { continue; } if (sinkInfo.SinkProperties.Contains(propertyReferenceOperation.Member.MetadataName)) { lazySinkKinds.Value.UnionWith(sinkInfo.SinkKinds); } } if (lazySinkKinds.IsValueCreated) { sinkKinds = lazySinkKinds.Value; return(true); } else { sinkKinds = null; return(false); } }
public override bool VisitPropertyReference([NotNull] IPropertyReferenceOperation operation1, [CanBeNull] IOperation argument) { return(argument is IPropertyReferenceOperation operation2 && AreBaseOperationsEqual(operation1, operation2) && AreSymbolsEqual(operation1.Property, operation2.Property) && AreSymbolsEqual(operation1.Member, operation2.Member)); }
public override void VisitPropertyReference(IPropertyReferenceOperation operation) { Assert.Equal(OperationKind.PropertyReference, operation.Kind); VisitMemberReference(operation, operation.Arguments); Assert.Same(operation.Member, operation.Property); }
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); }
public override void VisitPropertyReference([NotNull] IPropertyReferenceOperation operation) { NullCheckScanResult?scanResult = scanner.ScanPropertyReference(operation); SetScanResult(scanResult); base.VisitPropertyReference(operation); }
private static AbstractExpression ReadPropertyReference(IPropertyReferenceOperation op) { var context = CodeReaderContext.GetContextOrThrow(); return(new MemberExpression { Target = ReadExpression(op.Instance), Member = context.FindMemberOrThrow <PropertyMember>(op.Property) }); }
/// <summary> /// Workaround for https://github.com/dotnet/roslyn/issues/22736 (IPropertyReferenceExpressions in IAnonymousObjectCreationExpression are missing a receiver). /// Gets the instance for the anonymous object being created that is being referenced by <paramref name="operation"/>. /// Otherwise, returns null /// </summary> public static IAnonymousObjectCreationOperation GetAnonymousObjectCreation(this IPropertyReferenceOperation operation) { if (operation.Instance == null && operation.Property.ContainingType.IsAnonymousType) { var declarationSyntax = operation.Property.ContainingType.DeclaringSyntaxReferences[0].GetSyntax(); Func <IAnonymousObjectCreationOperation, bool> predicate = a => a.Syntax == declarationSyntax; return(operation.GetAncestor(OperationKind.AnonymousObjectCreation, predicate)); } return(null); }
private static void AnalyzePropertyReference(IPropertyReferenceOperation operation, OperationAnalysisContext context, string methodName) { operation = FindVirtualPropertyReference(operation); if (operation == null) { return; } if (IsLocalReference(operation.Instance)) { var diagnostic = Diagnostic.Create(LazyEvaluationInExpressionRule, operation.Syntax.GetLocation(), operation.Property.Name, methodName); context.ReportDiagnostic(diagnostic); } }
private static IPropertyReferenceOperation FindVirtualPropertyReference(IPropertyReferenceOperation operation) { if (operation.Property.IsVirtual) { return(operation); } IPropertyReferenceOperation instancePropertyReference = operation.Instance as IPropertyReferenceOperation; if (instancePropertyReference == null) { return(null); } return(FindVirtualPropertyReference(instancePropertyReference)); }
private static bool IsLocalReference(IOperation operation) { if (operation.Kind == OperationKind.LocalReference) { return(true); } IPropertyReferenceOperation propertyReference = operation as IPropertyReferenceOperation; if (propertyReference == null) { return(false); } return(IsLocalReference(propertyReference.Instance)); }
public StaticCallToMethodInjector( SolutionEditor helper, DocumentEditor editor, IOperation containingMethodOperation, IMethodSymbol containingMethodSymbol, IPropertyReferenceOperation propertyOperation, string defaultArgName) { DocEditor = editor; SlnEditor = helper; ContainingMethodSymbol = containingMethodSymbol; ContainingMethodOperation = containingMethodOperation; PropertyOperation = propertyOperation; _defaultArgumentName = defaultArgName; }
public NullCheckScanResult?ScanPropertyReference([NotNull] IPropertyReferenceOperation propertyReference) { Guard.NotNull(propertyReference, nameof(propertyReference)); if (propertyReference.Property.OriginalDefinition.Equals(knownSymbols.NullableHasValueProperty) && IsNullableValueType(propertyReference.Instance)) { NullCheckOperand nullCheckOperand = GetParentNullCheckOperand(propertyReference); return(new NullCheckScanResult(propertyReference.Instance, NullCheckMethod.NullableHasValueMethod, nullCheckOperand.Toggle())); } return(null); }
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 SyntaxNode CreateThrowIfCancellationRequestedExpressionStatement( DocumentEditor editor, IConditionalOperation conditional, IPropertyReferenceOperation isCancellationRequestedPropertyReference) { SyntaxNode memberAccess = editor.Generator.MemberAccessExpression( isCancellationRequestedPropertyReference.Instance.Syntax, nameof(CancellationToken.ThrowIfCancellationRequested)); SyntaxNode invocation = editor.Generator.InvocationExpression(memberAccess, Array.Empty <SyntaxNode>()); var firstWhenTrueStatement = conditional.WhenTrue is IBlockOperation block?block.Operations.FirstOrDefault() : conditional.WhenTrue; var result = editor.Generator.ExpressionStatement(invocation); result = firstWhenTrueStatement is not null?result.WithTriviaFrom(firstWhenTrueStatement.Syntax) : result; return(result.WithAdditionalAnnotations(Formatter.Annotation)); }
/// <summary> /// Provides a helper to raise a static property reference to an argument injected into the method. /// </summary> /// <param name="document">The document the property reference occurs in.</param> /// <param name="propertyReferenceOperation">The property reference operation.</param> /// <param name="methodOperation">The method operation the property reference occurs in.</param> /// <param name="methodSymbol">The method symbol where the property reference occurs.</param> /// <param name="defaultArgumentName">The default argument name that is injected.</param> /// <param name="token">A cancellation token.</param> /// <returns>An updated solution with the changes.</returns> public static async Task <Solution> MovePropertyAccessToMethodInjectionAsync( this Document document, IPropertyReferenceOperation propertyReferenceOperation, IOperation methodOperation, IMethodSymbol methodSymbol, string defaultArgumentName, CancellationToken token) { var slnEditor = new SolutionEditor(document.Project.Solution); var docEditor = await slnEditor.GetDocumentEditorAsync(document.Id, token).ConfigureAwait(false); var injector = new StaticCallToMethodInjector(slnEditor, docEditor, methodOperation, methodSymbol, propertyReferenceOperation, defaultArgumentName); await injector.MethodInjectPropertyAsync(token).ConfigureAwait(false); return(slnEditor.GetChangedSolution()); }
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 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 }; }
private void Analyze(OperationAnalysisContext context) { IPropertyReferenceOperation propertyReference = (IPropertyReferenceOperation)context.Operation; MemberAccessExpressionSyntax propertySyntax = propertyReference.Syntax as MemberAccessExpressionSyntax; if (propertySyntax == null) { return; } if (propertySyntax.Name.Identifier.ValueText == Identifier) { IPropertySymbol propertySymbol = propertyReference.Property; if (propertySymbol.ContainingNamespace.Name == ContainingNamespace && propertySymbol.ContainingType.Name.Contains(ContainingType)) { Diagnostic diagnostic = Diagnostic.Create(Rule, propertySyntax.Name.GetLocation()); context.ReportDiagnostic(diagnostic); } } }
/// <summary> /// プロパティ格納 /// </summary> /// <param name="prop">親プロパティ</param> private void SetProperty(IPropertyReferenceOperation prop) { if (prop.Property is IPropertySymbol propItem) { if (propItem.IsIndexer) { // インデクサの場合 Expressions.AddRange(OperationFactory.GetExpressionList(prop.Instance, eventContainer)); Expressions.Add(new Expression("[", string.Empty)); foreach (var arg in prop.Arguments) { if (!arg.Equals(prop.Arguments.First())) { Expressions.Add(new Expression(",", string.Empty)); } Expressions.AddRange(OperationFactory.GetExpressionList(arg, eventContainer)); } Expressions.Add(new Expression("]", string.Empty)); } else { // ローカルの場合はインスタンスを追加する if (prop.Instance is ILocalReferenceOperation) { Expressions.AddRange(OperationFactory.GetExpressionList(prop.Instance, eventContainer)); Expressions.Add(new Expression(".", string.Empty)); } // それ以外のプロパティの場合 Expressions.Add(new Expression(propItem.Name, Expression.GetSymbolTypeName(propItem))); } } else { // プロパティ以外の場合 Expressions.Add(new Expression(prop.Property.Name, Expression.GetSymbolTypeName(prop.Property))); } }
/// <summary> /// コンストラクタ /// </summary> /// <param name="operation">IOperationインスタンス</param> /// <param name="container">イベントコンテナ</param> public PropertyReference(IPropertyReferenceOperation operation, EventContainer container) : base(container) { // プロパティ参照情報を追加 if (!AddExpressions(operation.Instance)) { AddExpressions(operation); } else { if (operation.Instance is ILocalReferenceOperation) { // ローカルの場合はクリアする Expressions.Clear(); } else { // ローカル以外の場合はピリオドを設定 Expressions.Add(new Expression(".", string.Empty)); } // プロパティ格納 SetProperty(operation); } }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationContext) => { TaintedDataConfig taintedDataConfig = TaintedDataConfig.GetOrCreate(compilationContext.Compilation); TaintedDataSymbolMap <SourceInfo> sourceInfoSymbolMap = taintedDataConfig.GetSourceSymbolMap(this.SinkKind); if (sourceInfoSymbolMap.IsEmpty) { return; } TaintedDataSymbolMap <SinkInfo> sinkInfoSymbolMap = taintedDataConfig.GetSinkSymbolMap(this.SinkKind); if (sinkInfoSymbolMap.IsEmpty) { return; } compilationContext.RegisterOperationBlockStartAction( operationBlockStartContext => { ISymbol owningSymbol = operationBlockStartContext.OwningSymbol; if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options, TaintedDataEnteringSinkDescriptor, operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken)) { return; } PooledHashSet <IOperation> rootOperationsNeedingAnalysis = PooledHashSet <IOperation> .GetInstance(); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IPropertyReferenceOperation propertyReferenceOperation = (IPropertyReferenceOperation)operationAnalysisContext.Operation; IOperation rootOperation = operationAnalysisContext.Operation.GetRoot(); if (sourceInfoSymbolMap.IsSourceProperty(propertyReferenceOperation.Property)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(rootOperation); } } }, OperationKind.PropertyReference); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; IOperation rootOperation = operationAnalysisContext.Operation.GetRoot(); PooledDictionary <PointsToCheck, ImmutableHashSet <string> > evaluateWithPointsToAnalysis = null; PooledDictionary <ValueContentCheck, ImmutableHashSet <string> > evaluateWithValueContentAnalysis = null; PointsToAnalysisResult pointsToAnalysisResult = null; ValueContentAnalysisResult valueContentAnalysisResult = null; if (rootOperation.TryGetEnclosingControlFlowGraph(out ControlFlowGraph cfg)) { pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( cfg, owningSymbol, operationAnalysisContext.Options, WellKnownTypeProvider.GetOrCreate(operationAnalysisContext.Compilation), InterproceduralAnalysisConfiguration.Create( operationAnalysisContext.Options, SupportedDiagnostics, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive, cancellationToken: operationAnalysisContext.CancellationToken), interproceduralAnalysisPredicateOpt: null); if (pointsToAnalysisResult == null) { return; } } if (sourceInfoSymbolMap.RequiresValueContentAnalysis) { valueContentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( cfg, owningSymbol, operationAnalysisContext.Options, WellKnownTypeProvider.GetOrCreate(operationAnalysisContext.Compilation), InterproceduralAnalysisConfiguration.Create( operationAnalysisContext.Options, SupportedDiagnostics, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive, cancellationToken: operationAnalysisContext.CancellationToken), out var copyAnalysisResult, out pointsToAnalysisResult); if (valueContentAnalysisResult == null) { return; } } try { if (sourceInfoSymbolMap.IsSourceMethod( invocationOperation.TargetMethod, invocationOperation.Arguments, invocationOperation.Arguments.Select(o => pointsToAnalysisResult[o.Kind, o.Syntax]).ToImmutableArray(), invocationOperation.Arguments.Select(o => valueContentAnalysisResult[o.Kind, o.Syntax]).ToImmutableArray(), out _)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(rootOperation); } } } finally { evaluateWithPointsToAnalysis?.Free(); evaluateWithValueContentAnalysis?.Free(); } }, OperationKind.Invocation); if (taintedDataConfig.HasTaintArraySource(SinkKind)) { operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IArrayInitializerOperation arrayInitializerOperation = (IArrayInitializerOperation)operationAnalysisContext.Operation; if (arrayInitializerOperation.GetAncestor <IArrayCreationOperation>(OperationKind.ArrayCreation)?.Type is IArrayTypeSymbol arrayTypeSymbol && sourceInfoSymbolMap.IsSourceConstantArrayOfType(arrayTypeSymbol)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(operationAnalysisContext.Operation.GetRoot()); } } }, OperationKind.ArrayInitializer); } operationBlockStartContext.RegisterOperationBlockEndAction( operationBlockAnalysisContext => { try { lock (rootOperationsNeedingAnalysis) { if (!rootOperationsNeedingAnalysis.Any()) { return; } foreach (IOperation rootOperation in rootOperationsNeedingAnalysis) { if (!rootOperation.TryGetEnclosingControlFlowGraph(out var cfg)) { continue; } TaintedDataAnalysisResult taintedDataAnalysisResult = TaintedDataAnalysis.TryGetOrComputeResult( cfg, operationBlockAnalysisContext.Compilation, operationBlockAnalysisContext.OwningSymbol, operationBlockAnalysisContext.Options, TaintedDataEnteringSinkDescriptor, sourceInfoSymbolMap, taintedDataConfig.GetSanitizerSymbolMap(this.SinkKind), sinkInfoSymbolMap, operationBlockAnalysisContext.CancellationToken); 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.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceSink.Sink.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.Symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat) }); operationBlockAnalysisContext.ReportDiagnostic(diagnostic); } } } } } finally { rootOperationsNeedingAnalysis.Free(); } }); }); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationContext) => { Compilation compilation = compilationContext.Compilation; TaintedDataConfig taintedDataConfig = TaintedDataConfig.GetOrCreate(compilation); TaintedDataSymbolMap <SourceInfo> sourceInfoSymbolMap = taintedDataConfig.GetSourceSymbolMap(this.SinkKind); if (sourceInfoSymbolMap.IsEmpty) { return; } TaintedDataSymbolMap <SinkInfo> sinkInfoSymbolMap = taintedDataConfig.GetSinkSymbolMap(this.SinkKind); if (sinkInfoSymbolMap.IsEmpty) { return; } compilationContext.RegisterOperationBlockStartAction( operationBlockStartContext => { ISymbol owningSymbol = operationBlockStartContext.OwningSymbol; AnalyzerOptions options = operationBlockStartContext.Options; CancellationToken cancellationToken = operationBlockStartContext.CancellationToken; if (options.IsConfiguredToSkipAnalysis(TaintedDataEnteringSinkDescriptor, owningSymbol, compilation)) { 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); 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); ValueContentAnalysisResult?valuecontentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( controlFlowGraphFactory.Value, owningSymbol, options, wellKnownTypeProvider, PointsToAnalysisKind.Complete, interproceduralAnalysisConfiguration, out _, out PointsToAnalysisResult? p); return(p, valuecontentAnalysisResult); }); PooledHashSet <IOperation> 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.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 (TaintedDataConfig.HasTaintArraySource(SinkKind)) { 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, taintedDataConfig.GetSanitizerSymbolMap(this.SinkKind), sinkInfoSymbolMap); 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.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), 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 NullAbstractValue VisitPropertyReference(IPropertyReferenceOperation operation, object argument) { var _ = base.VisitPropertyReference(operation, argument); return(GetValueBasedOnInstanceOrReferenceValue(operation.Instance)); }
public override IOperation VisitPropertyReference(IPropertyReferenceOperation operation, object argument) { return(new PropertyReferenceExpression(operation.Property, Visit(operation.Instance), VisitArray(operation.Arguments), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit)); }
public override void VisitPropertyReference([NotNull] IPropertyReferenceOperation operation) { base.VisitPropertyReference(operation); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationContext) => { TaintedDataConfig taintedDataConfig = TaintedDataConfig.GetOrCreate(compilationContext.Compilation); TaintedDataSymbolMap <SourceInfo> sourceInfoSymbolMap = taintedDataConfig.GetSourceSymbolMap(this.SinkKind); if (sourceInfoSymbolMap.IsEmpty) { return; } TaintedDataSymbolMap <SinkInfo> sinkInfoSymbolMap = taintedDataConfig.GetSinkSymbolMap(this.SinkKind); if (sinkInfoSymbolMap.IsEmpty) { return; } compilationContext.RegisterOperationBlockStartAction( operationBlockStartContext => { ISymbol owningSymbol = operationBlockStartContext.OwningSymbol; HashSet <IOperation> rootOperationsNeedingAnalysis = new HashSet <IOperation>(); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IPropertyReferenceOperation propertyReferenceOperation = (IPropertyReferenceOperation)operationAnalysisContext.Operation; if (sourceInfoSymbolMap.IsSourceProperty(propertyReferenceOperation.Property)) { rootOperationsNeedingAnalysis.Add(operationAnalysisContext.Operation.GetRoot()); } }, OperationKind.PropertyReference); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; if (sourceInfoSymbolMap.IsSourceMethod(invocationOperation.TargetMethod)) { rootOperationsNeedingAnalysis.Add(operationAnalysisContext.Operation.GetRoot()); } }, OperationKind.Invocation); operationBlockStartContext.RegisterOperationBlockEndAction( operationBlockAnalysisContext => { if (!rootOperationsNeedingAnalysis.Any()) { return; } foreach (IOperation rootOperation in rootOperationsNeedingAnalysis) { TaintedDataAnalysisResult taintedDataAnalysisResult = TaintedDataAnalysis.GetOrComputeResult( rootOperation.GetEnclosingControlFlowGraph(), operationBlockAnalysisContext.Compilation, operationBlockAnalysisContext.OwningSymbol, operationBlockAnalysisContext.Options, TaintedDataEnteringSinkDescriptor, sourceInfoSymbolMap, taintedDataConfig.GetSanitizerSymbolMap(this.SinkKind), sinkInfoSymbolMap, operationBlockAnalysisContext.CancellationToken); 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.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceSink.Sink.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.Symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat) }); operationBlockAnalysisContext.ReportDiagnostic(diagnostic); } } } }); }); }); }
public virtual void VisitPropertyReference(IPropertyReferenceOperation operation) { DefaultVisit(operation); }
public override GlobalFlowStateAnalysisValueSet VisitPropertyReference(IPropertyReferenceOperation operation, object?argument) { return(GetValueOrDefault(base.VisitPropertyReference(operation, argument))); }