示例#1
0
            private void AnalyzeMethodOverloads(OperationAnalysisContext context, IMethodSymbol method, ImmutableArray <IArgumentOperation> arguments, SyntaxNode expressionSyntax)
            {
                if (method.MatchMethodDerivedByName(_xmlTypes.XmlDocument, SecurityMemberNames.Load) ||                                    //FxCop CA3056
                    method.MatchMethodDerivedByName(_xmlTypes.XmlDocument, SecurityMemberNames.LoadXml) ||                                 //FxCop CA3057
                    method.MatchMethodDerivedByName(_xmlTypes.XPathDocument, WellKnownMemberNames.InstanceConstructorName) ||              //FxCop CA3059
                    method.MatchMethodDerivedByName(_xmlTypes.XmlSchema, SecurityMemberNames.Read) ||                                      //FxCop CA3060
                    method.MatchMethodDerivedByName(_xmlTypes.DataSet, SecurityMemberNames.ReadXml) ||                                     //FxCop CA3063
                    method.MatchMethodDerivedByName(_xmlTypes.DataSet, SecurityMemberNames.ReadXmlSchema) ||                               //FxCop CA3064
                    method.MatchMethodDerivedByName(_xmlTypes.XmlSerializer, SecurityMemberNames.Deserialize) ||                           //FxCop CA3070
                    method.MatchMethodDerivedByName(_xmlTypes.DataTable, SecurityMemberNames.ReadXml) ||                                   //FxCop CA3071
                    method.MatchMethodDerivedByName(_xmlTypes.DataTable, SecurityMemberNames.ReadXmlSchema))                               //FxCop CA3072
                {
                    if (SecurityDiagnosticHelpers.HasXmlReaderParameter(method, _xmlTypes) < 0)
                    {
                        context.ReportDiagnostic(expressionSyntax.CreateDiagnostic(RuleDoNotUseDtdProcessingOverloads, method.Name));
                    }
                }
                else if (method.MatchMethodDerivedByName(_xmlTypes.XmlReader, SecurityMemberNames.Create))
                {
                    int xmlReaderSettingsIndex = SecurityDiagnosticHelpers.GetXmlReaderSettingsParameterIndex(method, _xmlTypes);

                    if (xmlReaderSettingsIndex < 0)
                    {
                        if (method.Parameters.Length == 1 &&
                            method.Parameters[0].RefKind == RefKind.None &&
                            method.Parameters[0].Type.SpecialType == SpecialType.System_String)
                        {
                            // inputUri can load be a URL.  Should further investigate if this is worth flagging.
                            context.ReportDiagnostic(expressionSyntax.CreateDiagnostic(RuleXmlReaderCreateWrongOverload));
                        }

                        // If no XmlReaderSettings are passed, then the default
                        // XmlReaderSettings are used, with DtdProcessing set to Prohibit.
                    }
                    else if (arguments.Length > xmlReaderSettingsIndex)
                    {
                        IArgumentOperation arg            = arguments[xmlReaderSettingsIndex];
                        ISymbol            settingsSymbol = arg.GetReferencedMemberOrLocalOrParameter();

                        if (settingsSymbol == null)
                        {
                            return;
                        }

                        // If we have no XmlReaderSettingsEnvironment, then we don't know.
                        if (_xmlReaderSettingsEnvironments.TryGetValue(settingsSymbol, out XmlReaderSettingsEnvironment env) &&
                            !env.IsDtdProcessingDisabled &&
                            !(env.IsSecureResolver && env.IsMaxCharactersFromEntitiesLimited))
                        {
                            var diag = env.IsConstructedInCodeBlock
                                ? expressionSyntax.CreateDiagnostic(RuleXmlReaderCreateInsecureConstructed)
                                : expressionSyntax.CreateDiagnostic(RuleXmlReaderCreateInsecureInput);

                            context.ReportDiagnostic(diag);
                        }
                    }
                }
            }
示例#2
0
 protected static void AnalyzeArrayLength(int length, SyntaxNode arrayCreationExpression, Action <Diagnostic> addDiagnostic)
 {
     if (length == 0)
     {
         addDiagnostic(arrayCreationExpression.CreateDiagnostic(UseEmptyEnumerableRule));
     }
     else if (length == 1)
     {
         addDiagnostic(arrayCreationExpression.CreateDiagnostic(UseSingletonEnumerableRule));
     }
 }
示例#3
0
        private static bool ReportDiagnosticIfNecessary(OperationAnalysisContext operationContext,
                                                        IOperation argumentValue,
                                                        SyntaxNode syntax,
                                                        ISymbol invokedSymbol,
                                                        ISymbol containingMethod)
        {
            if (argumentValue.Type.SpecialType != SpecialType.System_String || !argumentValue.ConstantValue.HasValue)
            {
                // We have a candidate for diagnostic. perform more precise dataflow analysis.
                var topmostBlock = argumentValue.GetTopmostParentBlock();
                if (topmostBlock != null)
                {
                    var cfg = ControlFlowGraph.Create(topmostBlock);
                    var wellKnownTypeProvider        = WellKnownTypeProvider.GetOrCreate(operationContext.Compilation);
                    var copyAnalysisResult           = CopyAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider);
                    var nullAnalysisResult           = NullAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider);
                    var pointsToAnalysisResult       = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, nullAnalysisResult);
                    var stringContentResult          = StringContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, copyAnalysisResult, nullAnalysisResult, pointsToAnalysisResult);
                    StringContentAbstractValue value = stringContentResult[argumentValue];
                    if (value.NonLiteralState == StringContainsNonLiteralState.No)
                    {
                        // The value is a constant literal or default/unitialized, so avoid flagging this usage.
                        return(false);
                    }
                }

                // Review if the symbol passed to {invocation} in {method/field/constructor/etc} has user input.
                operationContext.ReportDiagnostic(syntax.CreateDiagnostic(Rule,
                                                                          invokedSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                                                          containingMethod.Name));
                return(true);
            }

            return(false);
        }
        private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol obsoleteAttributeType)
        {
            // FxCop compat: only analyze externally visible symbols by default
            if (!context.Symbol.MatchesConfiguredVisibility(context.Options, Rule, context.CancellationToken))
            {
                return;
            }

            ImmutableArray <AttributeData> attributes = context.Symbol.GetAttributes();

            foreach (AttributeData attribute in attributes)
            {
                if (attribute.AttributeClass.Equals(obsoleteAttributeType))
                {
                    // ObsoleteAttribute has a constructor that takes no params and two
                    // other constructors that take a message as the first param.
                    // If there are no arguments specificed or if the message argument is empty
                    // then report a diagnostic.
                    if (attribute.ConstructorArguments.IsEmpty ||
                        string.IsNullOrEmpty(attribute.ConstructorArguments.First().Value as string))
                    {
                        SyntaxNode node = attribute.ApplicationSyntaxReference.GetSyntax();
                        context.ReportDiagnostic(node.CreateDiagnostic(Rule, context.Symbol.Name));
                    }
                }
            }
        }
        private static bool ReportDiagnosticIfNecessary(OperationAnalysisContext operationContext,
                                                        IOperation argumentValue,
                                                        SyntaxNode syntax,
                                                        ISymbol invokedSymbol,
                                                        ISymbol containingMethod)
        {
            if (argumentValue.Type.SpecialType != SpecialType.System_String || !argumentValue.ConstantValue.HasValue)
            {
                // We have a candidate for diagnostic. perform more precise dataflow analysis.
                var cfg = argumentValue.GetEnclosingControlFlowGraph();
                var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(operationContext.Compilation);
                var valueContentResult    = ValueContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider,
                                                                                    operationContext.Options, Rule, operationContext.CancellationToken);
                ValueContentAbstractValue value = valueContentResult[argumentValue.Kind, argumentValue.Syntax];
                if (value.NonLiteralState == ValueContainsNonLiteralState.No)
                {
                    // The value is a constant literal or default/unitialized, so avoid flagging this usage.
                    return(false);
                }

                // Review if the symbol passed to {invocation} in {method/field/constructor/etc} has user input.
                operationContext.ReportDiagnostic(syntax.CreateDiagnostic(Rule,
                                                                          invokedSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                                                          containingMethod.Name));
                return(true);
            }

            return(false);
        }
 protected void GetDiagnosticsForNode(SyntaxNode node, SemanticModel model, Action<Diagnostic> addDiagnostic)
 {
     var type = model.GetTypeInfo(node).Type;
     if (type != null && TypeHasWeakIdentity(type, model))
     {
         addDiagnostic(node.CreateDiagnostic(Rule, type.ToDisplayString()));
     }
 }
示例#7
0
        protected void GetDiagnosticsForNode(SyntaxNode node, SemanticModel model, Action <Diagnostic> addDiagnostic)
        {
            var type = model.GetTypeInfo(node).Type;

            if (type != null && TypeHasWeakIdentity(type, model))
            {
                addDiagnostic(node.CreateDiagnostic(Rule, type.ToDisplayString()));
            }
        }
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationContext =>
            {
                compilationContext.RegisterOperationBlockAction(operationBlockContext =>
                {
                    // Analyze externally visible methods with reference type parameters.
                    if (!(operationBlockContext.OwningSymbol is IMethodSymbol containingMethod) ||
                        !containingMethod.IsExternallyVisible() ||
                        !containingMethod.Parameters.Any(p => p.Type.IsReferenceType))
                    {
                        return;
                    }

                    // Bail out early if we have no parameter references in the method body.
                    if (!operationBlockContext.OperationBlocks.HasAnyOperationDescendant(OperationKind.ParameterReference))
                    {
                        return;
                    }

                    // Perform analysis of all direct/indirect parameter usages in the method to get all non-validated usages that can cause a null dereference.
                    ImmutableDictionary <IParameterSymbol, SyntaxNode> hazardousParameterUsages = null;
                    foreach (var operationBlock in operationBlockContext.OperationBlocks)
                    {
                        if (operationBlock is IBlockOperation topmostBlock)
                        {
                            hazardousParameterUsages = ParameterValidationAnalysis.GetOrComputeHazardousParameterUsages(
                                topmostBlock, operationBlockContext.Compilation, containingMethod,
                                operationBlockContext.Options, Rule, operationBlockContext.CancellationToken);
                            break;
                        }
                    }

                    if (hazardousParameterUsages != null)
                    {
                        foreach (var kvp in hazardousParameterUsages)
                        {
                            IParameterSymbol parameter = kvp.Key;
                            SyntaxNode node            = kvp.Value;

                            // In externally visible method '{0}', validate parameter '{1}' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.
                            var arg1       = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                            var arg2       = parameter.Name;
                            var diagnostic = node.CreateDiagnostic(Rule, arg1, arg2);
                            operationBlockContext.ReportDiagnostic(diagnostic);
                        }
                    }
                });
            });
        }
 private static void VerifySymbol(
     ISymbol?symbol,
     SyntaxNode node,
     Action <Diagnostic> reportDiagnostic,
     ImmutableDictionary <IAssemblySymbol, ImmutableSortedSet <string> > restrictedInternalsVisibleToMap,
     ConcurrentDictionary <INamespaceSymbol, bool> namespaceToIsBannedMap)
 {
     if (symbol != null &&
         IsBannedSymbol(symbol, restrictedInternalsVisibleToMap, namespaceToIsBannedMap))
     {
         var bannedSymbolDisplayString = symbol.ToDisplayString(SymbolDisplayFormats.QualifiedTypeAndNamespaceSymbolDisplayFormat);
         var assemblyName         = symbol.ContainingAssembly.Name;
         var restrictedNamespaces = string.Join(", ", restrictedInternalsVisibleToMap[symbol.ContainingAssembly]);
         var diagnostic           = node.CreateDiagnostic(Rule, bannedSymbolDisplayString, assemblyName, restrictedNamespaces);
         reportDiagnostic(diagnostic);
     }
 }
示例#10
0
        private static bool ReportDiagnosticIfNecessary(OperationAnalysisContext operationContext,
                                                        IOperation argumentValue,
                                                        SyntaxNode syntax,
                                                        ISymbol invokedSymbol,
                                                        ISymbol containingMethod)
        {
            if (argumentValue.Type.SpecialType != SpecialType.System_String || !argumentValue.ConstantValue.HasValue)
            {
                // Review if the symbol passed to {invocation} in {method/field/constructor/etc} has user input.
                operationContext.ReportDiagnostic(syntax.CreateDiagnostic(Rule,
                                                                          invokedSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                                                          containingMethod.Name));

                return(true);
            }

            return(false);
        }
示例#11
0
        private void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol obsoleteAttributeType)
        {
            ImmutableArray <AttributeData> attributes = context.Symbol.GetAttributes();

            foreach (AttributeData attribute in attributes)
            {
                if (attribute.AttributeClass.Equals(obsoleteAttributeType))
                {
                    // ObsoleteAttribute has a constructor that takes no params and two
                    // other constructors that take a message as the first param.
                    // If there are no arguments specificed or if the message argument is empty
                    // then report a diagnostic.
                    if (attribute.ConstructorArguments.IsEmpty ||
                        string.IsNullOrEmpty(attribute.ConstructorArguments.First().Value as string))
                    {
                        SyntaxNode node = attribute.ApplicationSyntaxReference.GetSyntax();
                        context.ReportDiagnostic(node.CreateDiagnostic(Rule, context.Symbol.Name));
                    }
                }
            }
        }
            private void AnalyzeObjectCreationForXmlDocument(OperationAnalysisContext context, ISymbol variable, IObjectCreationOperation objCreation)
            {
                // create new environment representation if does not already exist
                if (variable == null || !_xmlDocumentEnvironments.TryGetValue(variable, out var xmlDocumentEnvironment))
                {
                    xmlDocumentEnvironment = new XmlDocumentEnvironment(_isFrameworkSecure);
                }

                xmlDocumentEnvironment.XmlDocumentDefinition = objCreation.Syntax;
                SyntaxNode node = objCreation.Syntax;

                // initial XmlResolver secure value dependent on whether framework version secure
                // < .NET 4.5.2 insecure - XmlDocument would set XmlResolver as XmlUrlResolver
                // >= .NET 4.5.2 secure - XmlDocument would set XmlResolver as null
                bool isXmlDocumentSecureResolver = _isFrameworkSecure;

                if (!Equals(objCreation.Constructor.ContainingType, _xmlTypes.XmlDocument))
                {
                    isXmlDocumentSecureResolver = true;
                }

                // propertyInitlizer is not returned any more
                // and no way to get propertysymbol
                if (objCreation.Initializer != null)
                {
                    foreach (IOperation init in objCreation.Initializer.Initializers)
                    {
                        if (init is IAssignmentOperation assign)
                        {
                            var propValue = assign.Value;
                            if (assign.Target is not IPropertyReferenceOperation propertyReference)
                            {
                                continue;
                            }

                            var prop = propertyReference.Property;
                            if (prop.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, "XmlResolver"))
                            {
                                if (propValue is not IConversionOperation operation)
                                {
                                    return;
                                }

                                // if XmlResolver declared as XmlSecureResolver by initializer
                                if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes))
                                {
                                    isXmlDocumentSecureResolver = true;
                                }
                                // if XmlResolver declared as null by initializer
                                else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand))
                                {
                                    isXmlDocumentSecureResolver = true;
                                }
                                // otherwise insecure resolver
                                else
                                {
                                    context.ReportDiagnostic(assign.Syntax.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver));
                                    return;
                                }
                            }
                            else
                            {
                                AnalyzeNeverSetProperties(context, prop, assign.Syntax.GetLocation());
                            }
                        }
                    }
                }

                xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver;

                // if XmlDocument object not temporary, add environment to dictionary
                if (variable != null)
                {
                    _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment;
                }
                // else is temporary (variable null) and XmlResolver insecure, then report now
                else if (!xmlDocumentEnvironment.IsSecureResolver)
                {
                    context.ReportDiagnostic(node.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver));
                }

                return;
            }
示例#13
0
 protected Diagnostic CreateDiagnostic(SyntaxNode node)
 {
     return node.CreateDiagnostic(Rule);
 }
 public static Diagnostic CreateDiagnostic(
     this SyntaxNode node,
     DiagnosticDescriptor rule,
     ImmutableDictionary <string, string?>?properties,
     params object[] args)
 => node.CreateDiagnostic(rule, additionalLocations: ImmutableArray <Location> .Empty, properties, args);
 public static Diagnostic CreateDiagnostic(
     this SyntaxNode node,
     DiagnosticDescriptor rule,
     params object[] args)
 => node.CreateDiagnostic(rule, properties: null, args);
 protected override Diagnostic CreateDiagnostic(IMethodSymbol containingMethod, SyntaxNode catchNode)
 {
     return(catchNode.CreateDiagnostic(Rule, containingMethod.ToDisplayString()));
 }
示例#17
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationContext =>
            {
                compilationContext.RegisterOperationBlockAction(operationBlockContext =>
                {
                    // Analyze externally visible methods with reference type parameters.
                    if (operationBlockContext.OwningSymbol is not IMethodSymbol containingMethod ||
                        !containingMethod.IsExternallyVisible() ||
                        !containingMethod.Parameters.Any(p => p.Type.IsReferenceType) ||
                        operationBlockContext.Options.IsConfiguredToSkipAnalysis(Rule, containingMethod, operationBlockContext.Compilation))
                    {
                        return;
                    }

                    // Bail out for protected members of sealed classes if the entire overridden method chain
                    // is defined in the same assembly.
                    if (containingMethod.IsOverride &&
                        containingMethod.ContainingType.IsSealed)
                    {
                        var overriddenMethod    = containingMethod.OverriddenMethod;
                        var hasAssemblyMismatch = false;
                        while (overriddenMethod != null)
                        {
                            if (!Equals(overriddenMethod.ContainingAssembly, containingMethod.ContainingAssembly))
                            {
                                hasAssemblyMismatch = true;
                                break;
                            }

                            overriddenMethod = overriddenMethod.OverriddenMethod;
                        }

                        if (!hasAssemblyMismatch)
                        {
                            return;
                        }
                    }

                    // Bail out early if we have no parameter references in the method body.
                    if (!operationBlockContext.OperationBlocks.HasAnyOperationDescendant(OperationKind.ParameterReference))
                    {
                        return;
                    }

                    // Perform analysis of all direct/indirect parameter usages in the method to get all non-validated usages that can cause a null dereference.
                    ImmutableDictionary <IParameterSymbol, SyntaxNode>?hazardousParameterUsages = null;
                    foreach (var operationBlock in operationBlockContext.OperationBlocks)
                    {
                        if (operationBlock is IBlockOperation topmostBlock)
                        {
                            hazardousParameterUsages = ParameterValidationAnalysis.GetOrComputeHazardousParameterUsages(
                                topmostBlock, operationBlockContext.Compilation, containingMethod,
                                operationBlockContext.Options, Rule);
                            break;
                        }
                    }

                    if (hazardousParameterUsages != null)
                    {
                        foreach (var kvp in hazardousParameterUsages)
                        {
                            IParameterSymbol parameter = kvp.Key;
                            SyntaxNode node            = kvp.Value;

                            // Check if user has configured to skip extension method 'this' parameter analysis.
                            if (containingMethod.IsExtensionMethod &&
                                Equals(containingMethod.Parameters[0], parameter))
                            {
                                bool excludeThisParameterOption = operationBlockContext.Options.GetBoolOptionValue(
                                    optionName: EditorConfigOptionNames.ExcludeExtensionMethodThisParameter,
                                    rule: Rule,
                                    containingMethod,
                                    operationBlockContext.Compilation,
                                    defaultValue: false);
                                if (excludeThisParameterOption)
                                {
                                    continue;
                                }
                            }

                            // In externally visible method '{0}', validate parameter '{1}' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.
                            var arg1       = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                            var arg2       = parameter.Name;
                            var diagnostic = node.CreateDiagnostic(Rule, arg1, arg2);
                            operationBlockContext.ReportDiagnostic(diagnostic);
                        }
                    }
                });
            });
        }
示例#18
0
            private void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
            {
                var           invocation    = (TInvocationExpressionSyntax)context.Node;
                SemanticModel semanticModel = context.SemanticModel;

                ISymbol symbol = semanticModel.GetSymbolInfo(invocation, context.CancellationToken).Symbol;

                if (symbol == null || symbol.Kind != SymbolKind.Method || !symbol.Name.StartsWith("Register", StringComparison.Ordinal))
                {
                    return;
                }

                var method = (IMethodSymbol)symbol;

                NoteRegisterActionInvocation(method, invocation, semanticModel, context.CancellationToken);

                bool isRegisterSymbolAction         = IsRegisterAction(DiagnosticWellKnownNames.RegisterSymbolActionName, method, _analysisContext, _compilationStartAnalysisContext);
                bool isRegisterSyntaxNodeAction     = IsRegisterAction(DiagnosticWellKnownNames.RegisterSyntaxNodeActionName, method, _analysisContext, _compilationStartAnalysisContext, _codeBlockStartAnalysisContext);
                bool isRegisterCodeBlockStartAction = IsRegisterAction(DiagnosticWellKnownNames.RegisterCodeBlockStartActionName, method, _analysisContext, _compilationStartAnalysisContext);
                bool isRegisterOperationAction      = IsRegisterAction(DiagnosticWellKnownNames.RegisterOperationActionName, method, _analysisContext, _compilationStartAnalysisContext, _operationBlockStartAnalysisContext);

                if (isRegisterSymbolAction || isRegisterSyntaxNodeAction || isRegisterOperationAction)
                {
                    if (method.Parameters.Length == 2 && method.Parameters[1].IsParams)
                    {
                        IEnumerable <SyntaxNode>?arguments = GetArgumentExpressions(invocation);
                        if (arguments != null)
                        {
                            int argumentCount = arguments.Count();
                            if (argumentCount >= 1)
                            {
                                ITypeSymbol type = semanticModel.GetTypeInfo(arguments.First(), context.CancellationToken).ConvertedType;
                                if (type == null || type.Name.Equals(nameof(Action), StringComparison.Ordinal))
                                {
                                    if (argumentCount == 1)
                                    {
                                        DiagnosticDescriptor rule;
                                        if (isRegisterSymbolAction)
                                        {
                                            rule = MissingSymbolKindArgumentRule;
                                        }
                                        else if (isRegisterOperationAction)
                                        {
                                            rule = MissingOperationKindArgumentRule;
                                        }
                                        else
                                        {
                                            rule = MissingSyntaxKindArgumentRule;
                                        }

                                        SyntaxNode invocationExpression = GetInvocationExpression(invocation);
                                        Diagnostic diagnostic           = invocationExpression.CreateDiagnostic(rule);
                                        context.ReportDiagnostic(diagnostic);
                                    }
                                    else if (isRegisterSymbolAction)
                                    {
                                        foreach (SyntaxNode argument in arguments.Skip(1))
                                        {
                                            symbol = semanticModel.GetSymbolInfo(argument, context.CancellationToken).Symbol;
                                            if (symbol != null &&
                                                symbol.Kind == SymbolKind.Field &&
                                                _symbolKind.Equals(symbol.ContainingType) &&
                                                !s_supportedSymbolKinds.Contains(symbol.Name))
                                            {
                                                Diagnostic diagnostic = argument.CreateDiagnostic(UnsupportedSymbolKindArgumentRule, symbol.Name);
                                                context.ReportDiagnostic(diagnostic);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if (!method.TypeParameters.IsEmpty &&
                    (isRegisterSyntaxNodeAction || isRegisterCodeBlockStartAction))
                {
                    ITypeSymbol?typeArgument = null;
                    if (method.TypeParameters.Length == 1)
                    {
                        if (method.TypeParameters[0].Name == DiagnosticWellKnownNames.TLanguageKindEnumName)
                        {
                            typeArgument = method.TypeArguments[0];
                        }
                    }
                    else
                    {
                        ITypeParameterSymbol typeParam = method.TypeParameters.FirstOrDefault(t => t.Name == DiagnosticWellKnownNames.TLanguageKindEnumName);
                        if (typeParam != null)
                        {
                            int index = method.TypeParameters.IndexOf(typeParam);
                            typeArgument = method.TypeArguments[index];
                        }
                    }

                    if (typeArgument != null &&
                        typeArgument.TypeKind != TypeKind.TypeParameter &&
                        typeArgument.TypeKind != TypeKind.Error &&
                        !IsSyntaxKind(typeArgument))
                    {
                        Location location = typeArgument.Locations[0];
                        if (!location.IsInSource)
                        {
                            SyntaxNode invocationExpression = GetInvocationExpression(invocation);
                            location = invocationExpression.GetLocation();
                        }

                        Diagnostic diagnostic = Diagnostic.Create(InvalidSyntaxKindTypeArgumentRule, location, typeArgument.Name, DiagnosticWellKnownNames.TLanguageKindEnumName, method.Name);
                        context.ReportDiagnostic(diagnostic);
                    }
                }
            }
示例#19
0
            private void AnalyzeObjectCreationForXmlDocument(OperationAnalysisContext context, ISymbol variable, IObjectCreationOperation objCreation)
            {
                if (variable == null || !_xmlDocumentEnvironments.TryGetValue(variable, out var xmlDocumentEnvironment))
                {
                    xmlDocumentEnvironment = new XmlDocumentEnvironment
                    {
                        IsSecureResolver = false,
                        IsXmlResolverSet = false
                    };
                }

                xmlDocumentEnvironment.XmlDocumentDefinition = objCreation.Syntax;
                SyntaxNode node = objCreation.Syntax;
                bool       isXmlDocumentSecureResolver = false;

                if (!Equals(objCreation.Constructor.ContainingType, _xmlTypes.XmlDocument))
                {
                    isXmlDocumentSecureResolver = true;
                }

                // propertyInitlizer is not returned any more
                // and no way to get propertysymbol
                if (objCreation.Initializer != null)
                {
                    foreach (IOperation init in objCreation.Initializer.Initializers)
                    {
                        if (init is IAssignmentOperation assign)
                        {
                            var propValue = assign.Value;
                            if (!(assign.Target is IPropertyReferenceOperation propertyReference))
                            {
                                continue;
                            }

                            var prop = propertyReference.Property;
                            if (prop.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, "XmlResolver"))
                            {
                                if (!(propValue is IConversionOperation operation))
                                {
                                    return;
                                }

                                if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes))
                                {
                                    isXmlDocumentSecureResolver = true;
                                }
                                else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand))
                                {
                                    isXmlDocumentSecureResolver = true;
                                }
                                else // Non secure resolvers
                                {
                                    context.ReportDiagnostic(assign.Syntax.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver));
                                    return;
                                }
                            }
                            else
                            {
                                AnalyzeNeverSetProperties(context, prop, assign.Syntax.GetLocation());
                            }
                        }
                    }
                }

                xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver;

                if (variable != null)
                {
                    _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment;
                }
                else if (!xmlDocumentEnvironment.IsSecureResolver) // Insecure temp object
                {
                    context.ReportDiagnostic(node.CreateDiagnostic(RuleXmlDocumentWithNoSecureResolver));
                }

                return;
            }
示例#20
0
            private void AnalyzeNodeForXslCompiledTransformLoad(SyntaxNodeAnalysisContext context)
            {
                SyntaxNode    node         = context.Node;
                SemanticModel model        = context.SemanticModel;
                IMethodSymbol methodSymbol = _syntaxNodeHelper.GetCalleeMethodSymbol(node, model);

                if (SecurityDiagnosticHelpers.IsXslCompiledTransformLoad(methodSymbol, _xmlTypes))
                {
                    bool isSecureResolver;
                    bool isSecureSettings;
                    bool isSetInBlock;

                    int xmlResolverIndex  = SecurityDiagnosticHelpers.GetXmlResolverParameterIndex(methodSymbol, _xmlTypes);
                    int xsltSettingsIndex = SecurityDiagnosticHelpers.GetXsltSettingsParameterIndex(methodSymbol, _xmlTypes);

                    // Overloads with no XmlResolver and XstlSettings specified are secure since they all have folowing behavior:
                    //  1. An XmlUrlResolver with no user credentials is used to process any xsl:import or xsl:include elements.
                    //  2. The document() function is disabled.
                    //  3. Embedded scripts are not supported.
                    if (xmlResolverIndex >= 0 &&
                        xsltSettingsIndex >= 0)
                    {
                        IEnumerable <SyntaxNode> argumentExpressionNodes = _syntaxNodeHelper.GetInvocationArgumentExpressionNodes(node);
                        SyntaxNode resolverNode = argumentExpressionNodes.ElementAt(xmlResolverIndex);

                        isSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(resolverNode, model) ||
                                           SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(resolverNode).Type, _xmlTypes);

                        SyntaxNode settingsNode   = argumentExpressionNodes.ElementAt(xsltSettingsIndex);
                        ISymbol    settingsSymbol = SyntaxNodeHelper.GetSymbol(settingsNode, model);

                        // 1. pass null or XsltSettings.Default as XsltSetting : secure
                        if (settingsSymbol == null || SecurityDiagnosticHelpers.IsXsltSettingsDefaultProperty(settingsSymbol as IPropertySymbol, _xmlTypes))
                        {
                            isSetInBlock     = true;
                            isSecureSettings = true;
                        }
                        // 2. XsltSettings.TrustedXslt : insecure
                        else if (SecurityDiagnosticHelpers.IsXsltSettingsTrustedXsltProperty(settingsSymbol as IPropertySymbol, _xmlTypes))
                        {
                            isSetInBlock     = true;
                            isSecureSettings = false;
                        }
                        // 3. check xsltSettingsEnvironments, if IsScriptDisabled && IsDocumentFunctionDisabled then secure, else insecure
                        else if (_xsltSettingsEnvironments.TryGetValue(settingsSymbol, out XsltSettingsEnvironment env))
                        {
                            isSetInBlock     = false;
                            isSecureSettings = env.IsDocumentFunctionDisabled && env.IsScriptDisabled;
                        }
                        //4. symbol for settings is not found => passed in without any change => assume insecure
                        else
                        {
                            isSetInBlock     = true;
                            isSecureSettings = false;
                        }

                        if (!isSecureSettings && !isSecureResolver)
                        {
                            LocalizableResourceString message = SecurityDiagnosticHelpers.GetLocalizableResourceString(
                                isSetInBlock ? nameof(MicrosoftNetFrameworkAnalyzersResources.XslCompiledTransformLoadInsecureConstructedMessage) :
                                nameof(MicrosoftNetFrameworkAnalyzersResources.XslCompiledTransformLoadInsecureInputMessage),
                                SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model, context.CancellationToken)
                                );

                            context.ReportDiagnostic(
                                node.CreateDiagnostic(RuleDoNotUseInsecureXSLTScriptExecution, message)
                                );
                        }
                    }
                }
            }
 protected static Diagnostic CreateDiagnostic(SyntaxNode node)
 {
     return(node.CreateDiagnostic(Rule));
 }
示例#22
0
            public void Analyze(OperationAnalysisContext context, ISymbol owningSymbol)
            {
                if (context.Operation.IsInvalid)
                {
                    // not interested in invalid expression
                    return;
                }

                var           invocation = (IInvocationExpression)context.Operation;
                IMethodSymbol method     = invocation.TargetMethod;

                SyntaxNode node = _expressionGetter(context.Operation.Syntax);

                if (node == null)
                {
                    // we don't have right expression node to check overloads
                    return;
                }

                // REVIEW: why IOperation doesn't contain things like compilation and semantic model?
                //         it seems wierd that I need to do this to get thsoe.
                SemanticModel model = _compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree);

                // due to limitation of using "this" in lambda in struct
                INamedTypeSymbol stringType = _string;
                IEnumerable <IParameterSymbol> stringParameters = method.Parameters.Where(p => p.Type?.Equals(stringType) == true);

                if (!stringParameters.Any())
                {
                    // no string parameter. not interested.
                    return;
                }

                // now do cheap string check whether those string parameter contains uri word list we are looking for.
                if (!CheckStringParametersContainUriWords(stringParameters, context.CancellationToken))
                {
                    // no string parameter that contains what we are looking for.
                    return;
                }

                // now we make sure we actually have overloads that contains uri type parameter
                if (!CheckOverloadsContainUriParameters(model, method, node, context.CancellationToken))
                {
                    // no overload that contains uri as parameter
                    return;
                }

                // now we do more expensive word parsing to find exact parameter that contains url in parameter name
                var indicesSet = new HashSet <int>(GetParameterIndices(method, GetStringParametersThatContainsUriWords(stringParameters, context.CancellationToken), context.CancellationToken));

                // now we search exact match. this is exactly same behavior as old FxCop
                foreach (IMethodSymbol overload in model.GetMemberGroup(node, context.CancellationToken).OfType <IMethodSymbol>())
                {
                    context.CancellationToken.ThrowIfCancellationRequested();

                    if (method.Equals(overload) || overload.Parameters.Length != method.Parameters.Length)
                    {
                        // either itself, or signature is not same
                        continue;
                    }

                    if (!CheckParameterTypes(method, overload, Enumerable.Range(0, method.Parameters.Length).Where(i => !indicesSet.Contains(i)), context.CancellationToken))
                    {
                        // check whether remaining parameters match existing types, otherwise, we are not interested
                        continue;
                    }

                    // original FxCop implementation doesnt account for case where original method call contains
                    // 2+ string uri parameters that has overload with matching uri parameters. original implementation works
                    // when there is exactly 1 parameter having matching uri overload. this implementation follow that.
                    foreach (int index in indicesSet)
                    {
                        // check other string uri parameters matches original type
                        if (!CheckParameterTypes(method, overload, indicesSet.Where(i => i != index), context.CancellationToken))
                        {
                            continue;
                        }

                        // okay all other type match. check the main one
                        if (overload.Parameters[index].Type?.Equals(_uri) == true)
                        {
                            context.ReportDiagnostic(node.CreateDiagnostic(Rule, owningSymbol.ToDisplayString(s_symbolDisplayFormat), overload.ToDisplayString(s_symbolDisplayFormat), method.ToDisplayString(s_symbolDisplayFormat)));

                            // we no longer interested in this overload. there can be only 1 match
                            break;
                        }
                    }
                }
            }