public static PropertySetAnalysisContext Create( AbstractValueDomain <PropertySetAbstractValue> valueDomain, WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, PointsToAnalysisResult pointsToAnalysisResult, ValueContentAnalysisResult valueContentAnalysisResultOpt, Func <PropertySetAnalysisContext, PropertySetAnalysisResult> getOrComputeAnalysisResult, string typeToTrackMetadataName, ConstructorMapper constructorMapper, PropertyMapperCollection propertyMappers, HazardousUsageEvaluatorCollection hazardousUsageEvaluators) { return(new PropertySetAnalysisContext( valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult, valueContentAnalysisResultOpt, getOrComputeAnalysisResult, parentControlFlowGraphOpt: null, interproceduralAnalysisDataOpt: null, typeToTrackMetadataName: typeToTrackMetadataName, constructorMapper: constructorMapper, propertyMappers: propertyMappers, hazardousUsageEvaluators: hazardousUsageEvaluators, hazardousUsageTypesToNames: hazardousUsageEvaluators.GetTypeToNameMapping(wellKnownTypeProvider))); }
private PropertySetAnalysisContext( AbstractValueDomain <PropertySetAbstractValue> valueDomain, WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, PointsToAnalysisResult pointsToAnalysisResult, ValueContentAnalysisResult valueContentAnalysisResultOpt, Func <PropertySetAnalysisContext, PropertySetAnalysisResult> getOrComputeAnalysisResult, ControlFlowGraph parentControlFlowGraphOpt, InterproceduralPropertySetAnalysisData interproceduralAnalysisDataOpt, string typeToTrackMetadataName, ConstructorMapper constructorMapper, PropertyMapperCollection propertyMappers, HazardousUsageEvaluatorCollection hazardousUsageEvaluators, ImmutableDictionary <INamedTypeSymbol, string> hazardousUsageTypesToNames) : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: false, exceptionPathsAnalysis: false, copyAnalysisResultOpt: null, pointsToAnalysisResult, getOrComputeAnalysisResult, parentControlFlowGraphOpt, interproceduralAnalysisDataOpt, interproceduralAnalysisPredicateOpt: null) { this.ValueContentAnalysisResultOpt = valueContentAnalysisResultOpt; this.TypeToTrackMetadataName = typeToTrackMetadataName; this.ConstructorMapper = constructorMapper; this.PropertyMappers = propertyMappers; this.HazardousUsageEvaluators = hazardousUsageEvaluators; this.HazardousUsageTypesToNames = hazardousUsageTypesToNames; }
public override PropertySetAnalysisContext ForkForInterproceduralAnalysis( IMethodSymbol invokedMethod, ControlFlowGraph invokedCfg, IOperation operation, PointsToAnalysisResult pointsToAnalysisResultOpt, CopyAnalysisResult copyAnalysisResultOpt, ValueContentAnalysisResult valueContentAnalysisResultOpt, InterproceduralPropertySetAnalysisData interproceduralAnalysisData) { Debug.Assert(pointsToAnalysisResultOpt != null); Debug.Assert(copyAnalysisResultOpt == null); return(new PropertySetAnalysisContext( ValueDomain, WellKnownTypeProvider, invokedCfg, invokedMethod, InterproceduralAnalysisConfiguration, PessimisticAnalysis, pointsToAnalysisResultOpt, valueContentAnalysisResultOpt, GetOrComputeAnalysisResult, ControlFlowGraph, interproceduralAnalysisData, this.TypeToTrackMetadataName, this.ConstructorMapper, this.PropertyMappers, this.HazardousUsageEvaluators, this.HazardousUsageTypesToNames)); }
public abstract TAnalysisContext ForkForInterproceduralAnalysis( IMethodSymbol invokedMethod, ControlFlowGraph invokedCfg, IOperation operation, PointsToAnalysisResult pointsToAnalysisResultOpt, CopyAnalysisResult copyAnalysisResultOpt, ValueContentAnalysisResult valueContentAnalysisResultOpt, InterproceduralAnalysisData <TAnalysisData, TAnalysisContext, TAbstractAnalysisValue> interproceduralAnalysisData);
protected AbstractDataFlowAnalysisContext( AbstractValueDomain <TAbstractAnalysisValue> valueDomain, WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, bool predicateAnalysis, bool exceptionPathsAnalysis, CopyAnalysisResult copyAnalysisResultOpt, PointsToAnalysisResult pointsToAnalysisResultOpt, ValueContentAnalysisResult valueContentAnalysisResultOpt, Func <TAnalysisContext, TAnalysisResult> tryGetOrComputeAnalysisResult, ControlFlowGraph parentControlFlowGraphOpt, InterproceduralAnalysisData <TAnalysisData, TAnalysisContext, TAbstractAnalysisValue> interproceduralAnalysisDataOpt, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) { Debug.Assert(valueDomain != null, "valueDomain must not be null for use in ComputeHashCodeParts"); Debug.Assert(controlFlowGraph != null); Debug.Assert(owningSymbol != null); Debug.Assert(owningSymbol.Kind == SymbolKind.Method || owningSymbol.Kind == SymbolKind.Field || owningSymbol.Kind == SymbolKind.Property || owningSymbol.Kind == SymbolKind.Event); Debug.Assert(Equals(owningSymbol.OriginalDefinition, owningSymbol)); Debug.Assert(wellKnownTypeProvider != null); Debug.Assert(tryGetOrComputeAnalysisResult != null); Debug.Assert(pointsToAnalysisResultOpt == null || pointsToAnalysisResultOpt.ControlFlowGraph == controlFlowGraph); Debug.Assert(copyAnalysisResultOpt == null || copyAnalysisResultOpt.ControlFlowGraph == controlFlowGraph); Debug.Assert(valueContentAnalysisResultOpt == null || valueContentAnalysisResultOpt.ControlFlowGraph == controlFlowGraph); ValueDomain = valueDomain; WellKnownTypeProvider = wellKnownTypeProvider; ControlFlowGraph = controlFlowGraph; ParentControlFlowGraphOpt = parentControlFlowGraphOpt; OwningSymbol = owningSymbol; AnalyzerOptions = analyzerOptions; InterproceduralAnalysisConfiguration = interproceduralAnalysisConfig; PessimisticAnalysis = pessimisticAnalysis; PredicateAnalysis = predicateAnalysis; ExceptionPathsAnalysis = exceptionPathsAnalysis; CopyAnalysisResultOpt = copyAnalysisResultOpt; PointsToAnalysisResultOpt = pointsToAnalysisResultOpt; ValueContentAnalysisResultOpt = valueContentAnalysisResultOpt; TryGetOrComputeAnalysisResult = tryGetOrComputeAnalysisResult; InterproceduralAnalysisDataOpt = interproceduralAnalysisDataOpt; InterproceduralAnalysisPredicateOpt = interproceduralAnalysisPredicateOpt; }
public override CopyAnalysisContext ForkForInterproceduralAnalysis( IMethodSymbol invokedMethod, ControlFlowGraph invokedControlFlowGraph, IOperation operation, PointsToAnalysisResult pointsToAnalysisResultOpt, CopyAnalysisResult copyAnalysisResultOpt, ValueContentAnalysisResult valueContentAnalysisResultOpt, InterproceduralCopyAnalysisData interproceduralAnalysisData) { return(new CopyAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, AnalyzerOptions, InterproceduralAnalysisConfiguration, PessimisticAnalysis, ExceptionPathsAnalysis, pointsToAnalysisResultOpt, TryGetOrComputeAnalysisResult, ControlFlowGraph, interproceduralAnalysisData, InterproceduralAnalysisPredicateOpt)); }
protected sealed override void ComputeHashCodeParts(ref RoslynHashCode hashCode) { hashCode.Add(ValueDomain.GetHashCode()); hashCode.Add(OwningSymbol.GetHashCode()); hashCode.Add(ControlFlowGraph.GetHashCode()); hashCode.Add(AnalyzerOptions.GetHashCode()); hashCode.Add(InterproceduralAnalysisConfiguration.GetHashCode()); hashCode.Add(PessimisticAnalysis.GetHashCode()); hashCode.Add(PredicateAnalysis.GetHashCode()); hashCode.Add(ExceptionPathsAnalysis.GetHashCode()); hashCode.Add(CopyAnalysisResult.GetHashCodeOrDefault()); hashCode.Add(PointsToAnalysisResult.GetHashCodeOrDefault()); hashCode.Add(ValueContentAnalysisResult.GetHashCodeOrDefault()); hashCode.Add(InterproceduralAnalysisData.GetHashCodeOrDefault()); hashCode.Add(InterproceduralAnalysisPredicate.GetHashCodeOrDefault()); ComputeHashCodePartsSpecific(ref hashCode); }
protected sealed override void ComputeHashCodeParts(Action <int> addPart) { addPart(ValueDomain.GetHashCode()); addPart(OwningSymbol.GetHashCode()); addPart(ControlFlowGraph.GetHashCode()); addPart(AnalyzerOptions.GetHashCode()); addPart(InterproceduralAnalysisConfiguration.GetHashCode()); addPart(PessimisticAnalysis.GetHashCode()); addPart(PredicateAnalysis.GetHashCode()); addPart(ExceptionPathsAnalysis.GetHashCode()); addPart(CopyAnalysisResult.GetHashCodeOrDefault()); addPart(PointsToAnalysisResult.GetHashCodeOrDefault()); addPart(ValueContentAnalysisResult.GetHashCodeOrDefault()); addPart(InterproceduralAnalysisData.GetHashCodeOrDefault()); addPart(InterproceduralAnalysisPredicate.GetHashCodeOrDefault()); ComputeHashCodePartsSpecific(addPart); }
public override DisposeAnalysisContext ForkForInterproceduralAnalysis( IMethodSymbol invokedMethod, ControlFlowGraph invokedControlFlowGraph, IOperation operation, PointsToAnalysisResult pointsToAnalysisResultOpt, CopyAnalysisResult copyAnalysisResultOpt, ValueContentAnalysisResult valueContentAnalysisResultOpt, InterproceduralDisposeAnalysisData interproceduralAnalysisData) { Debug.Assert(pointsToAnalysisResultOpt != null); Debug.Assert(copyAnalysisResultOpt == null); Debug.Assert(valueContentAnalysisResultOpt == null); return(new DisposeAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, InterproceduralAnalysisConfiguration, PessimisticAnalysis, ExceptionPathsAnalysis, pointsToAnalysisResultOpt, TryGetOrComputeAnalysisResult, DisposeOwnershipTransferLikelyTypes, DisposeOwnershipTransferAtConstructor, DisposeOwnershipTransferAtMethodCall, TrackInstanceFields, ControlFlowGraph, interproceduralAnalysisData, InterproceduralAnalysisPredicateOpt)); }
private PropertySetAnalysisContext( AbstractValueDomain <PropertySetAbstractValue> valueDomain, WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, PointsToAnalysisResult pointsToAnalysisResult, ValueContentAnalysisResult valueContentAnalysisResultOpt, Func <PropertySetAnalysisContext, PropertySetAnalysisResult> tryGetOrComputeAnalysisResult, ControlFlowGraph parentControlFlowGraphOpt, InterproceduralPropertySetAnalysisData interproceduralAnalysisDataOpt, ImmutableHashSet <string> typeToTrackMetadataNames, ConstructorMapper constructorMapper, PropertyMapperCollection propertyMappers, HazardousUsageEvaluatorCollection hazardousUsageEvaluators, ImmutableDictionary <(INamedTypeSymbol, bool), string> hazardousUsageTypesToNames)
protected sealed override bool ComputeEqualsByHashCodeParts(CacheBasedEquatable <TAnalysisContext> obj) { var other = (AbstractDataFlowAnalysisContext <TAnalysisData, TAnalysisContext, TAnalysisResult, TAbstractAnalysisValue>)obj; return(ValueDomain.GetHashCode() == other.ValueDomain.GetHashCode() && OwningSymbol.GetHashCode() == other.OwningSymbol.GetHashCode() && ControlFlowGraph.GetHashCode() == other.ControlFlowGraph.GetHashCode() && AnalyzerOptions.GetHashCode() == other.AnalyzerOptions.GetHashCode() && InterproceduralAnalysisConfiguration.GetHashCode() == other.InterproceduralAnalysisConfiguration.GetHashCode() && PessimisticAnalysis.GetHashCode() == other.PessimisticAnalysis.GetHashCode() && PredicateAnalysis.GetHashCode() == other.PredicateAnalysis.GetHashCode() && ExceptionPathsAnalysis.GetHashCode() == other.ExceptionPathsAnalysis.GetHashCode() && CopyAnalysisResult.GetHashCodeOrDefault() == other.CopyAnalysisResult.GetHashCodeOrDefault() && PointsToAnalysisResult.GetHashCodeOrDefault() == other.PointsToAnalysisResult.GetHashCodeOrDefault() && ValueContentAnalysisResult.GetHashCodeOrDefault() == other.ValueContentAnalysisResult.GetHashCodeOrDefault() && InterproceduralAnalysisData.GetHashCodeOrDefault() == other.InterproceduralAnalysisData.GetHashCodeOrDefault() && InterproceduralAnalysisPredicate.GetHashCodeOrDefault() == other.InterproceduralAnalysisPredicate.GetHashCodeOrDefault() && ComputeEqualsByHashCodeParts(other)); }
public override ParameterValidationAnalysisContext ForkForInterproceduralAnalysis( IMethodSymbol invokedMethod, ControlFlowGraph invokedCfg, IOperation operation, PointsToAnalysisResult pointsToAnalysisResultOpt, CopyAnalysisResult copyAnalysisResultOpt, ValueContentAnalysisResult valueContentAnalysisResultOpt, InterproceduralParameterValidationAnalysisData interproceduralAnalysisData) { Debug.Assert(pointsToAnalysisResultOpt != null); Debug.Assert(copyAnalysisResultOpt == null); Debug.Assert(valueContentAnalysisResultOpt == null); // Do not invoke any interprocedural analysis more than one level down. // We only care about analyzing validation methods. return(new ParameterValidationAnalysisContext( ValueDomain, WellKnownTypeProvider, invokedCfg, invokedMethod, InterproceduralAnalysisConfiguration, PessimisticAnalysis, pointsToAnalysisResultOpt, GetOrComputeAnalysisResult, ControlFlowGraph, interproceduralAnalysisData, TrackHazardousParameterUsages)); }
private TaintedDataAnalysisContext( AbstractValueDomain <TaintedDataAbstractValue> valueDomain, WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, CopyAnalysisResult copyAnalysisResultOpt, PointsToAnalysisResult pointsToAnalysisResult, ValueContentAnalysisResult valueContentAnalysisResult, Func <TaintedDataAnalysisContext, TaintedDataAnalysisResult> tryGetOrComputeAnalysisResult, ControlFlowGraph parentControlFlowGraph, InterproceduralTaintedDataAnalysisData interproceduralAnalysisDataOpt, TaintedDataSymbolMap <SourceInfo> taintedSourceInfos, TaintedDataSymbolMap <SanitizerInfo> taintedSanitizerInfos, TaintedDataSymbolMap <SinkInfo> taintedSinkInfos) : base( valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: false, exceptionPathsAnalysis: false, copyAnalysisResultOpt, pointsToAnalysisResult, valueContentAnalysisResult, tryGetOrComputeAnalysisResult, parentControlFlowGraph, interproceduralAnalysisDataOpt, interproceduralAnalysisPredicateOpt: null) { Debug.Assert(pointsToAnalysisResult != null); this.SourceInfos = taintedSourceInfos ?? throw new ArgumentNullException(nameof(taintedSourceInfos)); this.SanitizerInfos = taintedSanitizerInfos ?? throw new ArgumentNullException(nameof(taintedSanitizerInfos)); this.SinkInfos = taintedSinkInfos ?? throw new ArgumentNullException(nameof(taintedSinkInfos)); }
public static TaintedDataAnalysisContext Create( AbstractValueDomain <TaintedDataAbstractValue> valueDomain, WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, CopyAnalysisResult copyAnalysisResultOpt, PointsToAnalysisResult pointsToAnalysisResult, ValueContentAnalysisResult valueContentAnalysisResult, Func <TaintedDataAnalysisContext, TaintedDataAnalysisResult> tryGetOrComputeAnalysisResult, TaintedDataSymbolMap <SourceInfo> taintedSourceInfos, TaintedDataSymbolMap <SanitizerInfo> taintedSanitizerInfos, TaintedDataSymbolMap <SinkInfo> taintedSinkInfos) { Debug.Assert(pointsToAnalysisResult != null); return(new TaintedDataAnalysisContext( valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, copyAnalysisResultOpt, pointsToAnalysisResult, valueContentAnalysisResult, tryGetOrComputeAnalysisResult, parentControlFlowGraph: null, interproceduralAnalysisDataOpt: null, taintedSourceInfos: taintedSourceInfos, taintedSanitizerInfos: taintedSanitizerInfos, taintedSinkInfos: taintedSinkInfos)); }
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 (owningSymbol.IsConfiguredToSkipAnalysis(options, TaintedDataEnteringSinkDescriptor, compilation, cancellationToken)) { return; } WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); InterproceduralAnalysisConfiguration interproceduralAnalysisConfiguration = InterproceduralAnalysisConfiguration.Create( options, SupportedDiagnostics, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive, cancellationToken: cancellationToken); Lazy <ControlFlowGraph> controlFlowGraphFactory = new Lazy <ControlFlowGraph>( () => operationBlockStartContext.OperationBlocks.GetControlFlowGraph()); Lazy <PointsToAnalysisResult> pointsToFactory = new Lazy <PointsToAnalysisResult>( () => { if (controlFlowGraphFactory.Value == null) { return(null); } return(PointsToAnalysis.TryGetOrComputeResult( controlFlowGraphFactory.Value, owningSymbol, options, wellKnownTypeProvider, interproceduralAnalysisConfiguration, interproceduralAnalysisPredicateOpt: null)); }); Lazy <(PointsToAnalysisResult, ValueContentAnalysisResult)> valueContentFactory = new Lazy <(PointsToAnalysisResult, ValueContentAnalysisResult)>( () => { if (controlFlowGraphFactory.Value == null) { return(null, null); } ValueContentAnalysisResult valuecontentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( controlFlowGraphFactory.Value, owningSymbol, options, wellKnownTypeProvider, 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); 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)) { 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, 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(); } }); }); }); }
private static TaintedDataAnalysisResult TryGetOrComputeResult( ControlFlowGraph cfg, Compilation compilation, ISymbol containingMethod, AnalyzerOptions analyzerOptions, TaintedDataSymbolMap <SourceInfo> taintedSourceInfos, TaintedDataSymbolMap <SanitizerInfo> taintedSanitizerInfos, TaintedDataSymbolMap <SinkInfo> taintedSinkInfos, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig) { if (cfg == null) { Debug.Fail("Expected non-null CFG"); return(null); } WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); ValueContentAnalysisResult valueContentAnalysisResult = null; CopyAnalysisResult copyAnalysisResult = null; PointsToAnalysisResult pointsToAnalysisResult = null; if (taintedSourceInfos.RequiresValueContentAnalysis || taintedSanitizerInfos.RequiresValueContentAnalysis || taintedSinkInfos.RequiresValueContentAnalysis) { valueContentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( cfg, containingMethod, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, out copyAnalysisResult, out pointsToAnalysisResult, pessimisticAnalysis: true, performCopyAnalysis: false); if (valueContentAnalysisResult == null) { return(null); } } else { pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( cfg, containingMethod, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis: true, performCopyAnalysis: false); if (pointsToAnalysisResult == null) { return(null); } } TaintedDataAnalysisContext analysisContext = TaintedDataAnalysisContext.Create( TaintedDataAbstractValueDomain.Default, wellKnownTypeProvider, cfg, containingMethod, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis: false, copyAnalysisResultOpt: copyAnalysisResult, pointsToAnalysisResult: pointsToAnalysisResult, valueContentAnalysisResult: valueContentAnalysisResult, tryGetOrComputeAnalysisResult: TryGetOrComputeResultForAnalysisContext, taintedSourceInfos: taintedSourceInfos, taintedSanitizerInfos: taintedSanitizerInfos, taintedSinkInfos: taintedSinkInfos); return(TryGetOrComputeResultForAnalysisContext(analysisContext)); }
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(); } }); }); }); }