Exemplo n.º 1
0
 private static void ReportOnWeakIdentityObject(IOperation operation, OperationAnalysisContext context)
 {
     if (operation is IInstanceReferenceOperation instanceReference &&
         instanceReference.ReferenceKind == InstanceReferenceKind.ContainingTypeInstance)
     {
         context.ReportDiagnostic(operation.CreateDiagnostic(Rule, operation.Syntax.ToString()));
     }
Exemplo n.º 2
0
        private void AnalyzeFormatArgument(OperationAnalysisContext context, IOperation formatExpression, int paramsCount, bool argsIsArray, bool usingLoggerExtensionsTypes, IMethodSymbol methodSymbol)
        {
            var text = TryGetFormatText(formatExpression);

            if (text == null)
            {
                if (usingLoggerExtensionsTypes)
                {
                    context.ReportDiagnostic(formatExpression.CreateDiagnostic(CA2254Rule, methodSymbol.ToDisplayString(GetLanguageSpecificFormat(formatExpression))));
                }
                return;
            }

            LogValuesFormatter formatter;

            try
            {
                formatter = new LogValuesFormatter(text);
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception)
#pragma warning restore CA1031 // Do not catch general exception types
            {
                return;
            }

            foreach (var valueName in formatter.ValueNames)
            {
                if (int.TryParse(valueName, out _))
                {
                    context.ReportDiagnostic(formatExpression.CreateDiagnostic(CA2253Rule));
                }
                else if (!string.IsNullOrEmpty(valueName) && char.IsLower(valueName[0]))
                {
                    context.ReportDiagnostic(formatExpression.CreateDiagnostic(CA1727Rule));
                }
            }

            var argsPassedDirectly = argsIsArray && paramsCount == 1;
            if (!argsPassedDirectly && paramsCount != formatter.ValueNames.Count)
            {
                context.ReportDiagnostic(formatExpression.CreateDiagnostic(CA2017Rule));
            }
        }
Exemplo n.º 3
0
                void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol? containingPropertySymbol, IOperation operation, Action <Diagnostic> reportDiagnostic, bool useNamingHeuristic)
                {
                    if (ShouldBeLocalized(parameter.OriginalDefinition, containingPropertySymbol?.OriginalDefinition, localizableStateAttributeSymbol, conditionalAttributeSymbol, systemConsoleSymbol, typesToIgnore, useNamingHeuristic) &&
                        lazyValueContentResult.Value != null)
                    {
                        ValueContentAbstractValue stringContentValue = lazyValueContentResult.Value[operation.Kind, operation.Syntax];
                        if (stringContentValue.IsLiteralState)
                        {
                            Debug.Assert(!stringContentValue.LiteralValues.IsEmpty);

                            if (stringContentValue.LiteralValues.Any(l => l is not string))
                            {
                                return;
                            }

                            var stringLiteralValues = stringContentValue.LiteralValues.Cast <string?>();

                            // 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.
                            IEnumerable <string> filteredStrings = stringLiteralValues.Where(literal => literal != null && !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);
                            }
                        }
                    }
                }
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationContext =>
            {
                INamedTypeSymbol?expectedExceptionType = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftVisualStudioTestToolsUnitTestingExpectedExceptionAttribute);
                INamedTypeSymbol?nunitAssertType       = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.NUnitFrameworkAssert);
                INamedTypeSymbol?xunitAssertType       = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.XunitAssert);
                INamedTypeSymbol?linqEnumerableType    = compilationContext.Compilation.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemLinqEnumerable);

                compilationContext.RegisterOperationBlockStartAction(osContext =>
                {
                    if (osContext.OwningSymbol is not IMethodSymbol method)
                    {
                        return;
                    }

                    osContext.RegisterOperationAction(opContext =>
                    {
                        IOperation expression = ((IExpressionStatementOperation)opContext.Operation).Operation;

                        var userDefinedMethods = compilationContext.Options.GetAdditionalUseResultsMethodsOption(UserDefinedMethodRule, expression.Syntax.SyntaxTree, compilationContext.Compilation, compilationContext.CancellationToken);

                        DiagnosticDescriptor?rule = null;
                        string targetMethodName   = "";
                        switch (expression.Kind)
                        {
                        case OperationKind.ObjectCreation:
                            IMethodSymbol ctor = ((IObjectCreationOperation)expression).Constructor;
                            if (ctor != null)
                            {
                                rule             = ObjectCreationRule;
                                targetMethodName = ctor.ContainingType.Name;
                            }
                            break;

                        case OperationKind.Invocation:
                            IInvocationOperation invocationExpression = (IInvocationOperation)expression;
                            IMethodSymbol targetMethod = invocationExpression.TargetMethod;
                            if (targetMethod.ReturnsVoid)
                            {
                                break;
                            }

                            if (IsStringCreatingMethod(targetMethod))
                            {
                                rule = StringCreationRule;
                            }
                            else if (IsTryParseMethod(targetMethod))
                            {
                                rule = TryParseRule;
                            }
                            else if (IsHResultOrErrorCodeReturningMethod(targetMethod))
                            {
                                rule = HResultOrErrorCodeRule;
                            }
                            else if (IsPureMethod(targetMethod, opContext.Compilation))
                            {
                                rule = PureMethodRule;
                            }
                            else if (targetMethod.ContainingType.Equals(linqEnumerableType))
                            {
                                rule = LinqMethodRule;
                            }
                            else if (userDefinedMethods.Contains(targetMethod.OriginalDefinition))
                            {
                                rule = UserDefinedMethodRule;
                            }

                            targetMethodName = targetMethod.Name;
                            break;
                        }

                        if (rule != null)
                        {
                            if (ShouldSkipAnalyzing(opContext, expectedExceptionType, xunitAssertType, nunitAssertType))
                            {
                                return;
                            }

                            Diagnostic diagnostic = expression.CreateDiagnostic(rule, method.Name, targetMethodName);
                            opContext.ReportDiagnostic(diagnostic);
                        }
                    }, OperationKind.ExpressionStatement);
                });
            });
        }
 public static Diagnostic CreateDiagnostic(
     this IOperation operation,
     DiagnosticDescriptor rule,
     params object[] args)
 => operation.CreateDiagnostic(rule, properties: null, args);
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

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

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

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

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

                        valueOperation = assignmentOperation.Value;
                        break;

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

                        valueOperation = argumentOperation.Value;
                        break;

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

                        valueOperation = returnOperation.ReturnedValue;
                        break;

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

                        valueOperation = variableInitializerOperation.Value;
                        break;

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

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

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

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

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

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

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

                return;

                // Local function(s).
                bool IsReferencingSslProtocols(
                    IFieldReferenceOperation fieldReferenceOperation,
                    out bool isDeprecatedProtocol,
                    out bool isHardcodedOkayProtocol)
                {
                    if (sslProtocolsSymbol.Equals(fieldReferenceOperation.Field.ContainingType))
                    {
                        if (HardcodedSslProtocolsMetadataNames.Contains(fieldReferenceOperation.Field.Name))
                        {
                            isHardcodedOkayProtocol = true;
                            isDeprecatedProtocol    = false;
                        }
                        else if (fieldReferenceOperation.Field.Name == "None")
                        {
                            isHardcodedOkayProtocol = false;
                            isDeprecatedProtocol    = false;
                        }
                        else
                        {
                            isDeprecatedProtocol    = true;
                            isHardcodedOkayProtocol = false;
                        }

                        return(true);
                    }
                    else
                    {
                        isHardcodedOkayProtocol = false;
                        isDeprecatedProtocol    = false;
                        return(false);
                    }
                }
            });
        }
Exemplo n.º 7
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

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

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartAnalysisContext.Compilation);
                if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemNetSecurityProtocolType,
                        out var securityProtocolTypeTypeSymbol) ||
                    !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName(
                        WellKnownTypeNames.SystemNetServicePointManager,
                        out var servicePointManagerTypeSymbol))
                {
                    return;
                }

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    var fieldReferenceOperation = (IFieldReferenceOperation)operationAnalysisContext.Operation;

                    // Make sure we're not inside an &= assignment like:
                    //   ServicePointManager.SecurityProtocol &= ~(SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11)
                    // cuz &= is at worst, disabling protocol versions.
                    if (IsReferencingSecurityProtocolType(
                            fieldReferenceOperation,
                            out var isDeprecatedProtocol,
                            out var isHardCodedOkayProtocol) &&
                        null == fieldReferenceOperation.GetAncestor <ICompoundAssignmentOperation>(
                            OperationKind.CompoundAssignment,
                            IsAndEqualsServicePointManagerAssignment))
                    {
                        if (isDeprecatedProtocol)
                        {
                            operationAnalysisContext.ReportDiagnostic(
                                fieldReferenceOperation.CreateDiagnostic(
                                    DeprecatedRule,
                                    fieldReferenceOperation.Field.Name));
                        }
                        else if (isHardCodedOkayProtocol)
                        {
                            operationAnalysisContext.ReportDiagnostic(
                                fieldReferenceOperation.CreateDiagnostic(
                                    HardCodedRule,
                                    fieldReferenceOperation.Field.Name));
                        }
                    }
                }, OperationKind.FieldReference);

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    var assignmentOperation = (IAssignmentOperation)operationAnalysisContext.Operation;

                    // Make sure this is an assignment operation for a SecurityProtocolType, and not
                    // an assignment like:
                    //   ServicePointManager.SecurityProtocol &= ~(SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11)
                    // cuz &= is at worst, disabling protocol versions.
                    if (!securityProtocolTypeTypeSymbol.Equals(assignmentOperation.Target.Type) ||
                        (assignmentOperation is ICompoundAssignmentOperation compoundAssignmentOperation &&
                         IsAndEqualsServicePointManagerAssignment(compoundAssignmentOperation)))
                    {
                        return;
                    }

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

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

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

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

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

                    if (foundHardCodedOperation != null && !foundHardCodedReference)
                    {
                        operationAnalysisContext.ReportDiagnostic(
                            foundHardCodedOperation.CreateDiagnostic(
                                HardCodedRule,
                                foundHardCodedOperation.ConstantValue));
                    }
                },
                    OperationKind.SimpleAssignment,
                    OperationKind.CompoundAssignment);

                return;

                // Local function(s).
                bool IsReferencingSecurityProtocolType(
                    IFieldReferenceOperation fieldReferenceOperation,
                    out bool isDeprecatedProtocol,
                    out bool isHardCodedOkayProtocol)
                {
                    if (securityProtocolTypeTypeSymbol.Equals(fieldReferenceOperation.Field.ContainingType))
                    {
                        if (HardCodedSafeProtocolMetadataNames.Contains(fieldReferenceOperation.Field.Name))
                        {
                            isHardCodedOkayProtocol = true;
                            isDeprecatedProtocol    = false;
                        }
                        else if (fieldReferenceOperation.Field.Name == SystemDefaultName)
                        {
                            isHardCodedOkayProtocol = false;
                            isDeprecatedProtocol    = false;
                        }
                        else
                        {
                            isDeprecatedProtocol    = true;
                            isHardCodedOkayProtocol = false;
                        }

                        return(true);
                    }
                    else
                    {
                        isHardCodedOkayProtocol = false;
                        isDeprecatedProtocol    = false;
                        return(false);
                    }
                }

                bool IsAndEqualsServicePointManagerAssignment(ICompoundAssignmentOperation compoundAssignmentOperation)
                {
                    return(compoundAssignmentOperation.OperatorKind == BinaryOperatorKind.And &&
                           compoundAssignmentOperation.Target is IPropertyReferenceOperation targetPropertyReference &&
                           targetPropertyReference.Instance == null &&
                           servicePointManagerTypeSymbol.Equals(targetPropertyReference.Property.ContainingType) &&
                           targetPropertyReference.Property.MetadataName == "SecurityProtocol");
                }
            });
        }
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationContext =>
            {
                compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext =>
                {
                    if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod))
                    {
                        return;
                    }

                    foreach (var operationRoot in operationBlockStartContext.OperationBlocks)
                    {
                        IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock();
                        if (topmostBlock != null && topmostBlock.HasAnyOperationDescendant(op => (op as IBinaryOperation)?.IsComparisonOperator() == true || op.Kind == OperationKind.Coalesce || op.Kind == OperationKind.ConditionalAccess))
                        {
                            var cfg = ControlFlowGraph.Create(topmostBlock);
                            var wellKnownTypeProvider  = WellKnownTypeProvider.GetOrCreate(operationBlockStartContext.Compilation);
                            var nullAnalysisResult     = NullAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider);
                            var pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, nullAnalysisResult);
                            var copyAnalysisResult     = CopyAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, nullAnalysisResultOpt: nullAnalysisResult, pointsToAnalysisResultOpt: pointsToAnalysisResult);
                            // Do another null analysis pass to improve the results from PointsTo and Copy analysis.
                            nullAnalysisResult = NullAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, copyAnalysisResult, pointsToAnalysisResultOpt: pointsToAnalysisResult);
                            var stringContentAnalysisResult = StringContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, copyAnalysisResult, nullAnalysisResult, pointsToAnalysisResult);

                            operationBlockStartContext.RegisterOperationAction(operationContext =>
                            {
                                PredicateValueKind GetPredicateKind(IBinaryOperation operation)
                                {
                                    if (operation.IsComparisonOperator())
                                    {
                                        PredicateValueKind binaryPredicateKind = nullAnalysisResult.GetPredicateKind(operation);
                                        if (binaryPredicateKind != PredicateValueKind.Unknown)
                                        {
                                            return(binaryPredicateKind);
                                        }

                                        binaryPredicateKind = copyAnalysisResult.GetPredicateKind(operation);
                                        if (binaryPredicateKind != PredicateValueKind.Unknown)
                                        {
                                            return(binaryPredicateKind);
                                        }

                                        binaryPredicateKind = stringContentAnalysisResult.GetPredicateKind(operation);
                                        if (binaryPredicateKind != PredicateValueKind.Unknown)
                                        {
                                            return(binaryPredicateKind);
                                        }
                                        ;
                                    }

                                    return(PredicateValueKind.Unknown);
                                }

                                var binaryOperation = (IBinaryOperation)operationContext.Operation;
                                PredicateValueKind predicateKind = GetPredicateKind(binaryOperation);
                                if (predicateKind != PredicateValueKind.Unknown &&
                                    (!(binaryOperation.LeftOperand is IBinaryOperation leftBinary) || GetPredicateKind(leftBinary) == PredicateValueKind.Unknown) &&
                                    (!(binaryOperation.RightOperand is IBinaryOperation rightBinary) || GetPredicateKind(rightBinary) == PredicateValueKind.Unknown))
                                {
                                    // '{0}' is always '{1}'. Remove or refactor the condition(s) to avoid dead code.
                                    var arg1 = binaryOperation.Syntax.ToString();
                                    var arg2 = predicateKind == PredicateValueKind.AlwaysTrue ?
                                               (binaryOperation.Language == LanguageNames.VisualBasic ? "True" : "true") :
                                               (binaryOperation.Language == LanguageNames.VisualBasic ? "False" : "false");
                                    var diagnostic = binaryOperation.CreateDiagnostic(AlwaysTrueFalseOrNullRule, arg1, arg2);
                                    operationContext.ReportDiagnostic(diagnostic);
                                }
                            }, OperationKind.BinaryOperator);

                            operationBlockStartContext.RegisterOperationAction(operationContext =>
                            {
                                IOperation nullCheckedOperation = operationContext.Operation.Kind == OperationKind.Coalesce ?
                                                                  ((ICoalesceOperation)operationContext.Operation).Value :
                                                                  ((IConditionalAccessOperation)operationContext.Operation).Operation;

                                // '{0}' is always/never '{1}'. Remove or refactor the condition(s) to avoid dead code.
                                DiagnosticDescriptor rule;
                                switch (nullAnalysisResult[nullCheckedOperation])
                                {
                                case NullAbstractValue.Null:
                                    rule = AlwaysTrueFalseOrNullRule;
                                    break;

                                case NullAbstractValue.NotNull:
                                    rule = NeverNullRule;
                                    break;

                                default:
                                    return;
                                }

                                var arg1       = nullCheckedOperation.Syntax.ToString();
                                var arg2       = nullCheckedOperation.Language == LanguageNames.VisualBasic ? "Nothing" : "null";
                                var diagnostic = nullCheckedOperation.CreateDiagnostic(rule, arg1, arg2);
                                operationContext.ReportDiagnostic(diagnostic);
                            }, OperationKind.Coalesce, OperationKind.ConditionalAccess);
                        }
                    }
                });
            });
        }
Exemplo n.º 9
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();

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

            context.RegisterCompilationStartAction(
                (CompilationStartAnalysisContext compilationStartAnalysisContext) =>
            {
                var securityProtocolTypeTypeSymbol = compilationStartAnalysisContext.Compilation.GetTypeByMetadataName(WellKnownTypeNames.SystemNetSecurityProtocolType);

                if (securityProtocolTypeTypeSymbol == null)
                {
                    return;
                }

                bool IsReferencingSecurityProtocolType(
                    IFieldReferenceOperation fieldReferenceOperation,
                    out bool isDeprecatedProtocol,
                    out bool isHardCodedOkayProtocol)
                {
                    if (securityProtocolTypeTypeSymbol.Equals(fieldReferenceOperation.Field.ContainingType))
                    {
                        if (HardCodedSafeProtocolMetadataNames.Contains(fieldReferenceOperation.Field.Name))
                        {
                            isHardCodedOkayProtocol = true;
                            isDeprecatedProtocol    = false;
                        }
                        else if (fieldReferenceOperation.Field.Name == SystemDefaultName)
                        {
                            isHardCodedOkayProtocol = false;
                            isDeprecatedProtocol    = false;
                        }
                        else
                        {
                            isDeprecatedProtocol    = true;
                            isHardCodedOkayProtocol = false;
                        }

                        return(true);
                    }
                    else
                    {
                        isHardCodedOkayProtocol = false;
                        isDeprecatedProtocol    = false;
                        return(false);
                    }
                }

                compilationStartAnalysisContext.RegisterOperationAction(
                    (OperationAnalysisContext operationAnalysisContext) =>
                {
                    var fieldReferenceOperation = (IFieldReferenceOperation)operationAnalysisContext.Operation;
                    if (IsReferencingSecurityProtocolType(
                            fieldReferenceOperation,
                            out var isDeprecatedProtocol,
                            out var isHardCodedOkayProtocol))
                    {
                        if (isDeprecatedProtocol)
                        {
                            operationAnalysisContext.ReportDiagnostic(
                                fieldReferenceOperation.CreateDiagnostic(
                                    DeprecatedRule,
                                    fieldReferenceOperation.Field.Name));
                        }
                        else if (isHardCodedOkayProtocol)
                        {
                            operationAnalysisContext.ReportDiagnostic(
                                fieldReferenceOperation.CreateDiagnostic(
                                    HardCodedRule,
                                    fieldReferenceOperation.Field.Name));
                        }
                    }
                }, OperationKind.FieldReference);

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

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

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

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

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

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

                    if (foundHardCodedOperation != null && !foundHardCodedReference)
                    {
                        operationAnalysisContext.ReportDiagnostic(
                            foundHardCodedOperation.CreateDiagnostic(
                                HardCodedRule,
                                foundHardCodedOperation.ConstantValue));
                    }
                },
                    OperationKind.SimpleAssignment,
                    OperationKind.CompoundAssignment);
            });
        }