private void AnalyzeAssignment(OperationAnalysisContext context) { var assignmentOperation = (ISimpleAssignmentOperation)context.Operation; // Check if there are more then one assignment in a statement if (assignmentOperation.Target is not IMemberReferenceOperation operationTarget) { return; } // This analyzer makes sense only for reference type objects if (operationTarget.Instance?.Type?.IsReferenceType != true) { return; } bool isViolationFound = operationTarget.Instance switch { ILocalReferenceOperation localInstance => AnalyzeAssignmentToMember(assignmentOperation, localInstance, (a, b) => a.Local.Equals(b.Local)), IMemberReferenceOperation memberInstance => AnalyzeAssignmentToMember(assignmentOperation, memberInstance, (a, b) => a.Member.Equals(b.Member) && a.Instance?.Syntax.ToString() == b.Instance?.Syntax.ToString()), IParameterReferenceOperation parameterInstance => AnalyzeAssignmentToMember(assignmentOperation, parameterInstance, (a, b) => a.Parameter.Equals(b.Parameter)), _ => false, }; if (isViolationFound) { var diagnostic = operationTarget.CreateDiagnostic(Rule, operationTarget.Instance.Syntax, operationTarget.Member.Name); context.ReportDiagnostic(diagnostic); } }
// Local functions static bool IsArgumentValueEqual(IOperation targetArg, IOperation valueArg) { // Check if arguments are identical constant/local/parameter reference operations. // 1. Not identical: 'this[i] = this[j]' // 2. Identical: 'this[i] = this[i]', 'this[0] = this[0]' if (targetArg.Kind != valueArg.Kind) { return(false); } if (targetArg.ConstantValue.HasValue != valueArg.ConstantValue.HasValue) { return(false); } if (targetArg.ConstantValue.HasValue) { return(Equals(targetArg.ConstantValue.Value, valueArg.ConstantValue.Value)); } #pragma warning disable IDE0055 // Fix formatting - Does not seem to be handling switch expressions. return(targetArg switch { ILocalReferenceOperation targetLocalReference => Equals(targetLocalReference.Local, ((ILocalReferenceOperation)valueArg).Local), IParameterReferenceOperation targetParameterReference => Equals(targetParameterReference.Parameter, ((IParameterReferenceOperation)valueArg).Parameter), _ => false, });
internal static ISymbol?GetUnderlyingSymbol(IOperation?operation) { return(operation switch { IParameterReferenceOperation paramRef => paramRef.Parameter, ILocalReferenceOperation localRef => localRef.Local, IMemberReferenceOperation memberRef => memberRef.Member, _ => null, });
public override IdentifierInfo VisitParameterReference([NotNull] IParameterReferenceOperation operation, [CanBeNull] object argument) { var name = new IdentifierName(operation.Parameter.Name, /* CSharpShortErrorMessageFormat returns 'int', ie. without parameter name */ operation.Parameter.Name); return(new IdentifierInfo(name, operation.Parameter.Type)); }
private static AbstractExpression ReadParameterReference(IParameterReferenceOperation op) { var context = CodeReaderContext.GetContextOrThrow(); return(new ParameterExpression() { // TODO: implement properly }); }
public override void VisitParameterReference(IParameterReferenceOperation operation) { var visitor = new NullableParameterVisitor(); visitor.Visit(operation.Parameter); if (visitor.IsNullableParameter) { MatchedNullableParameter = operation.Parameter; } }
protected override ITypeSymbol GetSymbolType( SemanticModel semanticModel, ISymbol symbol ) { var selectionOperation = semanticModel.GetOperation( SelectionResult.GetContainingScope() ); switch (symbol) { case ILocalSymbol localSymbol when localSymbol.NullableAnnotation == NullableAnnotation.Annotated: case IParameterSymbol parameterSymbol when parameterSymbol.NullableAnnotation == NullableAnnotation.Annotated: // For local symbols and parameters, we can check what the flow state // for refences to the symbols are and determine if we can change // the nullability to a less permissive state. var references = selectionOperation .DescendantsAndSelf() .Where(IsSymbolReferencedByOperation); if (AreAllReferencesNotNull(references)) { return(base.GetSymbolType(semanticModel, symbol) .WithNullableAnnotation(NullableAnnotation.NotAnnotated)); } return(base.GetSymbolType(semanticModel, symbol)); default: return(base.GetSymbolType(semanticModel, symbol)); } bool AreAllReferencesNotNull(IEnumerable <IOperation> references) => references.All( r => semanticModel.GetTypeInfo(r.Syntax).Nullability.FlowState == NullableFlowState.NotNull ); bool IsSymbolReferencedByOperation(IOperation operation) => operation switch { ILocalReferenceOperation localReference => localReference.Local.Equals(symbol), IParameterReferenceOperation parameterReference => parameterReference.Parameter.Equals(symbol), IAssignmentOperation assignment => IsSymbolReferencedByOperation(assignment.Target), _ => false }; } }
public override IdentifierInfo VisitParameterReference([NotNull] IParameterReferenceOperation operation, [CanBeNull] object argument) { var name = new IdentifierName(operation.Parameter.Name, #pragma warning disable AV2310 // Code blocks should not contain inline comments /* CSharpShortErrorMessageFormat returns 'int', ie. without parameter name */ #pragma warning restore AV2310 // Code blocks should not contain inline comments operation.Parameter.Name); return(new IdentifierInfo(name, operation.Parameter.Type, operation.Parameter.Kind.ToString())); }
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 override PointsToAbstractValue VisitParameterReference(IParameterReferenceOperation operation, object argument) { // Create a dummy PointsTo value for each reference type parameter. if (!operation.Type.HasValueCopySemantics()) { var result = AnalysisEntityFactory.TryCreateForSymbolDeclaration(operation.Parameter, out AnalysisEntity analysisEntity); Debug.Assert(result); if (!HasAbstractValue(analysisEntity)) { var value = new PointsToAbstractValue(AbstractLocation.CreateAllocationLocation(operation, operation.Parameter.Type)); SetAbstractValue(analysisEntity, value); return(value); } return(GetAbstractValue(analysisEntity)); } else { return(PointsToAbstractValue.NoLocation); } }
public override MultiValue VisitParameterReference(IParameterReferenceOperation paramRef, StateValue state) { return(paramRef.Parameter.Type.IsTypeInterestingForDataflow() ? new MethodParameterValue(paramRef.Parameter) : TopValue); }
public override IOperation VisitParameterReference(IParameterReferenceOperation operation, object argument) { return(new ParameterReferenceExpression(operation.Parameter, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit)); }
public override Scope VisitParameterReference(IParameterReferenceOperation operation, Scope currentScope) => currentScope;
public override void VisitParameterReference(IParameterReferenceOperation operation) { Assert.Equal(OperationKind.ParameterReference, operation.Kind); Assert.NotNull(operation.Parameter); Assert.Empty(operation.Children); }
public override GlobalFlowStateDictionaryAnalysisValue VisitParameterReference(IParameterReferenceOperation operation, object?argument) { var value = base.VisitParameterReference(operation, argument); return(VisitLocalOrParameter(operation.Parameter.Type?.OriginalDefinition, operation, value)); }
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 virtual void VisitParameterReference(IParameterReferenceOperation operation) { DefaultVisit(operation); }
/// <summary> /// コンストラクタ /// </summary> /// <param name="operation">IOperationインスタンス</param> /// <param name="container">イベントコンテナ</param> public ParameterReference(IParameterReferenceOperation operation, EventContainer container) : base(container) { var symbol = operation.Parameter; Expressions.Add(new Expression(symbol.Name, Expression.GetSymbolTypeName(symbol))); }
public override void VisitParameterReference([NotNull] IParameterReferenceOperation operation) { base.VisitParameterReference(operation); }
public override TAbstractAnalysisValue VisitParameterReference(IParameterReferenceOperation operation, object argument) { return(GetAbstractValue(operation.Parameter)); }
public override bool VisitParameterReference([NotNull] IParameterReferenceOperation operation1, [CanBeNull] IOperation argument) { return(argument is IParameterReferenceOperation operation2 && AreBaseOperationsEqual(operation1, operation2) && AreSymbolsEqual(operation1.Parameter, operation2.Parameter)); }
public override void VisitParameterReference(IParameterReferenceOperation operation) { var parameter = operation.Parameter; base.VisitParameterReference(operation); }
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 TAbstractAnalysisValue VisitParameterReference(IParameterReferenceOperation operation, object argument) { var value = base.VisitParameterReference(operation, argument); return(ComputeAnalysisValueForReferenceOperation(operation, value)); }
public override Scope VisitParameterReference(IParameterReferenceOperation operation, Scope currentScope) => currentScope.Union( new ParameterValue(operation.Parameter) );