private static ImmutableDictionary <IParameterSymbol, SyntaxNode> GetOrComputeHazardousParameterUsages( IBlockOperation topmostBlock, Compilation compilation, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, SymbolNamesWithValueOption <Unit> nullCheckValidationMethods, PointsToAnalysisKind pointsToAnalysisKind, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool performCopyAnalysis, bool pessimisticAnalysis) { var cfg = topmostBlock.GetEnclosingControlFlowGraph(); if (cfg == null) { return(ImmutableDictionary <IParameterSymbol, SyntaxNode> .Empty); } var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); var pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, pointsToAnalysisKind, interproceduralAnalysisConfig, interproceduralAnalysisPredicate: null, pessimisticAnalysis, performCopyAnalysis); if (pointsToAnalysisResult != null) { var result = TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult); if (result != null) { return(result.HazardousParameterUsages); } } return(ImmutableDictionary <IParameterSymbol, SyntaxNode> .Empty); }
private static ImmutableDictionary <IParameterSymbol, SyntaxNode> GetOrComputeHazardousParameterUsages( IBlockOperation topmostBlock, Compilation compilation, ISymbol owningSymbol, ImmutableArray <string> nullCheckValidationMethods, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool performCopyAnalysis, bool pessimisticAnalysis = true) { Debug.Assert(topmostBlock != null); var cfg = topmostBlock.GetEnclosingControlFlowGraph(); var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); var pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis, performCopyAnalysis); if (pointsToAnalysisResult != null) { var result = TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult); if (result != null) { return(result.HazardousParameterUsages); } } return(ImmutableDictionary <IParameterSymbol, SyntaxNode> .Empty); }
public bool TryGetOrComputeResult( ImmutableArray <IOperation> operationBlocks, IMethodSymbol containingMethod, AnalyzerOptions analyzerOptions, DiagnosticDescriptor rule, bool trackInstanceFields, bool trackExceptionPaths, CancellationToken cancellationToken, out DisposeAnalysisResult disposeAnalysisResult, out PointsToAnalysisResult pointsToAnalysisResult, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt = null, bool defaultDisposeOwnershipTransferAtConstructor = false) { foreach (var operationRoot in operationBlocks) { IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock(); if (topmostBlock != null) { var cfg = topmostBlock.GetEnclosingControlFlowGraph(); disposeAnalysisResult = DisposeAnalysis.GetOrComputeResult(cfg, containingMethod, _wellKnownTypeProvider, analyzerOptions, rule, _disposeOwnershipTransferLikelyTypes, trackInstanceFields, trackExceptionPaths, cancellationToken, out pointsToAnalysisResult, interproceduralAnalysisPredicateOpt: interproceduralAnalysisPredicateOpt, defaultDisposeOwnershipTransferAtConstructor: defaultDisposeOwnershipTransferAtConstructor); return(true); } } disposeAnalysisResult = null; pointsToAnalysisResult = null; return(false); }
public static ImmutableDictionary <IParameterSymbol, SyntaxNode> GetOrComputeHazardousParameterUsages( IBlockOperation topmostBlock, Compilation compilation, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, DiagnosticDescriptor rule, CancellationToken cancellationToken, PointsToAnalysisKind defaultPointsToAnalysisKind = PointsToAnalysisKind.PartialWithoutTrackingFieldsAndProperties, InterproceduralAnalysisKind interproceduralAnalysisKind = InterproceduralAnalysisKind.ContextSensitive, uint defaultMaxInterproceduralMethodCallChain = 1, // By default, we only want to track method calls one level down. bool pessimisticAnalysis = false) { Debug.Assert(!analyzerOptions.IsConfiguredToSkipAnalysis(rule, owningSymbol, compilation, cancellationToken)); var cfg = topmostBlock.GetEnclosingControlFlowGraph(); if (cfg == null) { return(ImmutableDictionary <IParameterSymbol, SyntaxNode> .Empty); } var interproceduralAnalysisConfig = InterproceduralAnalysisConfiguration.Create( analyzerOptions, rule, cfg, compilation, interproceduralAnalysisKind, cancellationToken, defaultMaxInterproceduralMethodCallChain); var performCopyAnalysis = analyzerOptions.GetCopyAnalysisOption(rule, topmostBlock.Syntax.SyntaxTree, compilation, defaultValue: false, cancellationToken); var nullCheckValidationMethods = analyzerOptions.GetNullCheckValidationMethodsOption(rule, topmostBlock.Syntax.SyntaxTree, compilation, cancellationToken); var pointsToAnalysisKind = analyzerOptions.GetPointsToAnalysisKindOption(rule, topmostBlock.Syntax.SyntaxTree, compilation, defaultPointsToAnalysisKind, cancellationToken); return(GetOrComputeHazardousParameterUsages(cfg, compilation, owningSymbol, analyzerOptions, nullCheckValidationMethods, pointsToAnalysisKind, interproceduralAnalysisConfig, performCopyAnalysis, pessimisticAnalysis)); }
public static ControlFlowGraph GetControlFlowGraph(this ImmutableArray <IOperation> operationBlocks) { foreach (var operationRoot in operationBlocks) { IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock(); if (topmostBlock != null) { return(topmostBlock.GetEnclosingControlFlowGraph()); } } return(null); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { INamedTypeSymbol localizableStateAttributeSymbol = WellKnownTypes.LocalizableAttribute(compilationContext.Compilation); INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationContext.Compilation); INamedTypeSymbol systemConsoleSymbol = WellKnownTypes.Console(compilationContext.Compilation); ImmutableHashSet <INamedTypeSymbol> typesToIgnore = GetTypesToIgnore(compilationContext.Compilation); compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext => { if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod)) { return; } var lazyValueContentResult = new Lazy <DataFlowAnalysisResult <ValueContentBlockAnalysisResult, ValueContentAbstractValue> >( valueFactory: ComputeValueContentAnalysisResult, isThreadSafe: false); operationBlockStartContext.RegisterOperationAction(operationContext => { var argument = (IArgumentOperation)operationContext.Operation; switch (argument.Parent?.Kind) { case OperationKind.Invocation: case OperationKind.ObjectCreation: AnalyzeArgument(argument.Parameter, containingPropertySymbolOpt: null, operation: argument, reportDiagnostic: operationContext.ReportDiagnostic); return; } }, OperationKind.Argument); operationBlockStartContext.RegisterOperationAction(operationContext => { var propertyReference = (IPropertyReferenceOperation)operationContext.Operation; if (propertyReference.Parent is IAssignmentOperation assignment && assignment.Target == propertyReference && !propertyReference.Property.IsIndexer && propertyReference.Property.SetMethod?.Parameters.Length == 1) { IParameterSymbol valueSetterParam = propertyReference.Property.SetMethod.Parameters[0]; AnalyzeArgument(valueSetterParam, propertyReference.Property, assignment, operationContext.ReportDiagnostic); } }, OperationKind.PropertyReference); void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol containingPropertySymbolOpt, IOperation operation, Action <Diagnostic> reportDiagnostic) { if (ShouldBeLocalized(parameter, containingPropertySymbolOpt, localizableStateAttributeSymbol, conditionalAttributeSymbol, systemConsoleSymbol, typesToIgnore)) { ValueContentAbstractValue stringContentValue = lazyValueContentResult.Value[operation.Kind, operation.Syntax]; if (stringContentValue.IsLiteralState) { Debug.Assert(stringContentValue.LiteralValues.Count > 0); if (stringContentValue.LiteralValues.Any(l => !(l is string))) { return; } var stringLiteralValues = stringContentValue.LiteralValues.Select(l => (string)l); // FxCop compat: Do not fire if the literal value came from a default parameter value if (stringContentValue.LiteralValues.Count == 1 && parameter.IsOptional && parameter.ExplicitDefaultValue is string defaultValue && defaultValue == stringLiteralValues.Single()) { return; } // FxCop compat: Do not fire if none of the string literals have any non-control character. if (!LiteralValuesHaveNonControlCharacters(stringLiteralValues)) { return; } // FxCop compat: Filter out xml string literals. var filteredStrings = stringLiteralValues.Where(literal => !LooksLikeXmlTag(literal)); if (filteredStrings.Any()) { // Method '{0}' passes a literal string as parameter '{1}' of a call to '{2}'. Retrieve the following string(s) from a resource table instead: "{3}". var arg1 = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); var arg2 = parameter.Name; var arg3 = parameter.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); var arg4 = FormatLiteralValues(filteredStrings); var diagnostic = operation.CreateDiagnostic(Rule, arg1, arg2, arg3, arg4); reportDiagnostic(diagnostic); } } } } DataFlowAnalysisResult <ValueContentBlockAnalysisResult, ValueContentAbstractValue> ComputeValueContentAnalysisResult() { foreach (var operationRoot in operationBlockStartContext.OperationBlocks) { IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock(); if (topmostBlock != null) { var cfg = topmostBlock.GetEnclosingControlFlowGraph(); var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(operationBlockStartContext.Compilation); return(ValueContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, operationBlockStartContext.Options, Rule, operationBlockStartContext.CancellationToken)); } } return(null); } }); }); }