From 1e3538e0e65e1f3e4a33a8a631828fc83ad1354b Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 25 Jul 2019 17:18:39 -0700 Subject: [PATCH 1/2] Add configuration support for existing editorconfig option `excluded_symbol_names` to all DFA rules All the DFA rules now respect the editorconfig option that allows skipping analysis for specified excluded symbols with `excluded_symbol_names` option. --- docs/Analyzer Configuration.md | 10 +- .../PublicAPI.Unshipped.txt | 9 +- .../AvoidDeadConditionalCode.cs | 6 + .../ValidateArgumentsOfPublicMethods.cs | 4 +- .../AvoidDeadConditionalCode_NullAnalysis.cs | 53 +++++++ .../ValidateArgumentsOfPublicMethodsTests.cs | 47 +++++++ ...iewSqlQueriesForSecurityVulnerabilities.cs | 7 +- .../DisposableFieldsShouldBeDisposed.cs | 5 +- .../DisposeObjectsBeforeLosingScope.cs | 4 +- .../DoNotPassLiteralsAsLocalizedParameters.cs | 4 +- ...rchiveItemPathToTheTargetFileSystemPath.cs | 4 +- .../Core/Security/DoNotInstallRootCert.cs | 12 ++ .../Core/Security/DoNotSetSwitch.cs | 16 ++- .../Core/Security/DoNotUseDSA.cs | 2 +- ...eserializerBinaryFormatterWithoutBinder.cs | 6 +- ...ascriptSerializerWithSimpleTypeResolver.cs | 18 ++- ...rNetDataContractSerializerWithoutBinder.cs | 6 +- ...seInsecureDeserializerWithoutBinderBase.cs | 12 ++ .../DoNotUseInsecureSettingsForJsonNet.cs | 18 ++- ...NotUseWeakKDFInsufficientIterationCount.cs | 12 +- .../SourceTriggeredTaintedDataAnalyzerBase.cs | 8 ++ .../Security/UseContainerLevelAccessPolicy.cs | 6 + .../Security/UseRSAWithSufficientKeySize.cs | 2 +- .../Security/UseSecureCookiesASPNetCore.cs | 10 ++ .../UseSharedAccessProtocolHttpsOnly.cs | 6 + ...LQueriesForSecurityVulnerabilitiesTests.cs | 53 +++++++ .../DisposableFieldsShouldBeDisposedTests.cs | 74 ++++++++++ .../DisposeObjectsBeforeLosingScopeTests.cs | 131 ++++++++++++++++++ ...tPassLiteralsAsLocalizedParametersTests.cs | 36 +++++ ...eItemPathToTheTargetFileSystemPathTests.cs | 30 ++++ .../DoNotDisableSchUseStrongCryptoTests.cs | 29 ++++ ...rvicePointManagerSecurityProtocolsTests.cs | 31 +++++ .../Security/DoNotInstallRootCertTests.cs | 33 +++++ ...alizerBinaryFormatterWithoutBinderTests.cs | 52 +++++++ ...ptSerializerWithSimpleTypeResolverTests.cs | 36 +++++ ...DoNotUseInsecureSettingsForJsonNetTests.cs | 37 +++++ ...eWeakKDFInsufficientIterationCountTests.cs | 33 +++++ .../Security/TaintedDataAnalyzerTestBase.cs | 11 ++ .../UseContainerLevelAccessPolicyTests.cs | 50 ++++++- .../UseSecureCookiesASPNetCoreTests.cs | 51 ++++++- .../UseSharedAccessProtocolHttpsOnlyTests.cs | 51 ++++++- .../DiagnosticAnalyzerTestBase.cs | 66 ++++++--- .../PropertySetAnalysisTests.cs | 1 + .../CategorizedAnalyzerConfigOptions.cs | 19 ++- .../Analysis/CopyAnalysis/CopyAnalysis.cs | 6 +- .../CopyAnalysis/CopyAnalysisContext.cs | 9 +- .../DisposeAnalysis/DisposeAnalysis.cs | 10 +- .../DisposeAnalysis/DisposeAnalysisContext.cs | 9 +- .../ParameterValidationAnalysis.cs | 12 +- .../ParameterValidationAnalysisContext.cs | 11 +- .../PointsToAnalysis/PointsToAnalysis.cs | 8 +- .../PointsToAnalysisContext.cs | 9 +- .../PropertySetAnalysis.cs | 7 + .../PropertySetAnalysisContext.cs | 6 + .../TaintedDataAnalysis.cs | 6 +- .../TaintedDataAnalysisContext.cs | 6 + .../ValueContentAnalysis.cs | 11 +- .../ValueContentAnalysisContext.cs | 9 +- .../AbstractDataFlowAnalysisContext.cs | 5 + .../DataFlow/DataFlowOperationVisitor.cs | 13 +- 60 files changed, 1151 insertions(+), 97 deletions(-) diff --git a/docs/Analyzer Configuration.md b/docs/Analyzer Configuration.md index 442184d588..e137ec3179 100644 --- a/docs/Analyzer Configuration.md +++ b/docs/Analyzer Configuration.md @@ -3,12 +3,13 @@ Starting with version `2.6.3`, all the analyzer NuGet packages produced in this repo, including the FxCop Analyzers NuGet package, support _.editorconfig based analyzer configuration_. End users can configure the behavior of specific CA rule(s) OR all configurable CA rules by specifying supported key-value pair options in an `.editorconfig` file. You can read more about `.editorconfig` format [here](https://editorconfig.org/). ## .editorconfig format -Analyzer configuration options from an .editorconfig file are parsed into _general_ and _specific_ configuration options. General configuration enables configuring the behavior of all CA rules for which the provided option is valid. Specific configuration enables configuring each CA rule ID or CA rules belonging to each rule category, such as 'Naming', 'Design', 'Performance', etc. Our options are _case-insensitive_. Below are the supported formats: +Analyzer configuration options from an .editorconfig file are parsed into _general_ and _specific_ configuration options. General configuration enables configuring the behavior of all CA rules for which the provided option is valid. Specific configuration enables configuring each CA rule ID or CA rules belonging to each rule category, such as 'Naming', 'Design', 'Performance', etc. or CA rules with a specific custom tag, such as 'Dataflow'. Our options are _case-insensitive_. Below are the supported formats: 1. General configuration option: 1. `dotnet_code_quality.OptionName = OptionValue` 2. Specific configuration option: 1. `dotnet_code_quality.RuleId.OptionName = OptionValue` 2. `dotnet_code_quality.RuleCategory.OptionName = OptionValue` + 2. `dotnet_code_quality.RuleCustomTag.OptionName = OptionValue` For example, end users can configure the analyzed API surface for analyzers using the below `api_surface` option specification: 1. General configuration option: @@ -16,6 +17,7 @@ For example, end users can configure the analyzed API surface for analyzers usin 2. Specific configuration option: 1. `dotnet_code_quality.CA1040.api_surface = public` 2. `dotnet_code_quality.Naming.api_surface = public` + 3. `dotnet_code_quality.Dataflow.api_surface = public` ## Enabling .editorconfig based configuration for a project 1. Per-project .editorconfig file: End users can enable .editorconfig based configuration for individual projects by just copying the .editorconfig file with the options to the project root directory. In future, we plan to support hierarchical directory based configuration with an .editorconfig file at the solution directory, repo root directory or even individual document directories. @@ -111,7 +113,7 @@ Examples: ### Excluded symbol names Option Name: `excluded_symbol_names` -Configurable Rules: [CA1303](https://docs.microsoft.com/visualstudio/code-quality/ca1303-do-not-pass-literals-as-localized-parameters) +Configurable Rules: [CA1303](https://docs.microsoft.com/visualstudio/code-quality/ca1303-do-not-pass-literals-as-localized-parameters), [CA1062](https://docs.microsoft.com/visualstudio/code-quality/ca1062-validate-arguments-of-public-methods), CA1508, [CA2000](https://docs.microsoft.com/visualstudio/code-quality/ca2000-dispose-objects-before-losing-scope), [CA2100](https://docs.microsoft.com/visualstudio/code-quality/ca2100-review-sql-queries-for-security-vulnerabilities), [CA2301](https://docs.microsoft.com/visualstudio/code-quality/ca2301-do-not-call-binaryformatter-deserialize-without-first-setting-binaryformatter-binder), [CA2302](https://docs.microsoft.com/visualstudio/code-quality/ca2302-ensure-binaryformatter-binder-is-set-before-calling-binaryformatter-deserialize), [CA2311](https://docs.microsoft.com/visualstudio/code-quality/ca2311-do-not-deserialize-without-first-setting-netdatacontractserializer-binder), [CA2312](https://docs.microsoft.com/visualstudio/code-quality/ca2312-ensure-netdatacontractserializer-binder-is-set-before-deserializing), [CA2321](https://docs.microsoft.com/visualstudio/code-quality/ca2321), [CA2322](https://docs.microsoft.com/visualstudio/code-quality/ca2322), CA2327, CA2328, [CA3001](https://docs.microsoft.com/visualstudio/code-quality/ca3001-review-code-for-sql-injection-vulnerabilities), [CA3002](https://docs.microsoft.com/visualstudio/code-quality/ca3002-review-code-for-xss-vulnerabilities), [CA3003](https://docs.microsoft.com/visualstudio/code-quality/ca3003-review-code-for-file-path-injection-vulnerabilities), [CA3004](https://docs.microsoft.com/visualstudio/code-quality/ca3004-review-code-for-information-disclosure-vulnerabilities), [CA3005](https://docs.microsoft.com/visualstudio/code-quality/ca3005-review-code-for-ldap-injection-vulnerabilities), [CA3006](https://docs.microsoft.com/visualstudio/code-quality/ca3006-review-code-for-process-command-injection-vulnerabilities), [CA3007](https://docs.microsoft.com/visualstudio/code-quality/ca3007-review-code-for-open-redirect-vulnerabilities), [CA3008](https://docs.microsoft.com/visualstudio/code-quality/ca3008-review-code-for-xpath-injection-vulnerabilities), [CA3009](https://docs.microsoft.com/visualstudio/code-quality/ca3009-review-code-for-xml-injection-vulnerabilities), [CA3010](https://docs.microsoft.com/visualstudio/code-quality/ca3010-review-code-for-xaml-injection-vulnerabilities), [CA3011](https://docs.microsoft.com/visualstudio/code-quality/ca3011-review-code-for-dll-injection-vulnerabilities), [CA3012](https://docs.microsoft.com/visualstudio/code-quality/ca3012-review-code-for-regex-injection-vulnerabilities), CA5361, CA5376, CA5377, CA5378, CA5380, CA5381, CA5382, CA5383, CA5384, CA5387, CA5388, CA5389, CA5390 Option Values: Names of symbols (separated by '|') that are excluded for analysis. Allowed symbol name formats: @@ -130,7 +132,9 @@ Examples: |`dotnet_code_quality.excluded_symbol_names = Validate1|Validate2` | Matches all symbols named either 'Validate1' or 'Validate2' in the compilation |`dotnet_code_quality.excluded_symbol_names = M:NS.MyType.Validate(ParamType)` | Matches specific method 'Validate' with given fully qualified signature |`dotnet_code_quality.excluded_symbol_names = M:NS1.MyType1.Validate1(ParamType)|M:NS2.MyType2.Validate2(ParamType)` | Matches specific methods 'Validate1' and 'Validate2' with respective fully qualified signature - + +Additionally, all the dataflow analysis based rules can be configured with a single entry `dotnet_code_quality.dataflow.excluded_symbol_names = ...` + ### Excluded type names with derived types Option Name: `excluded_type_names_with_derived_types` diff --git a/src/Microsoft.CodeAnalysis.FlowAnalysis.Utilities/PublicAPI.Unshipped.txt b/src/Microsoft.CodeAnalysis.FlowAnalysis.Utilities/PublicAPI.Unshipped.txt index d80451dd69..93b47f9eff 100644 --- a/src/Microsoft.CodeAnalysis.FlowAnalysis.Utilities/PublicAPI.Unshipped.txt +++ b/src/Microsoft.CodeAnalysis.FlowAnalysis.Utilities/PublicAPI.Unshipped.txt @@ -34,7 +34,8 @@ Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractBlockAnalysisResult Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractBlockAnalysisResult.AbstractBlockAnalysisResult(Microsoft.CodeAnalysis.FlowAnalysis.BasicBlock basicBlock) -> void Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractBlockAnalysisResult.BasicBlock.get -> Microsoft.CodeAnalysis.FlowAnalysis.BasicBlock Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractDataFlowAnalysisContext -Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractDataFlowAnalysisContext.AbstractDataFlowAnalysisContext(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractValueDomain valueDomain, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.WellKnownTypeProvider wellKnownTypeProvider, Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph controlFlowGraph, Microsoft.CodeAnalysis.ISymbol owningSymbol, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, bool predicateAnalysis, bool exceptionPathsAnalysis, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult copyAnalysisResultOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysisResult pointsToAnalysisResultOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult valueContentAnalysisResultOpt, System.Func tryGetOrComputeAnalysisResult, Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph parentControlFlowGraphOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisData interproceduralAnalysisDataOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) -> void +Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractDataFlowAnalysisContext.AbstractDataFlowAnalysisContext(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractValueDomain valueDomain, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.WellKnownTypeProvider wellKnownTypeProvider, Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph controlFlowGraph, Microsoft.CodeAnalysis.ISymbol owningSymbol, Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions analyzerOptions, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, bool predicateAnalysis, bool exceptionPathsAnalysis, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult copyAnalysisResultOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysisResult pointsToAnalysisResultOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult valueContentAnalysisResultOpt, System.Func tryGetOrComputeAnalysisResult, Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph parentControlFlowGraphOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisData interproceduralAnalysisDataOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) -> void +Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractDataFlowAnalysisContext.AnalyzerOptions.get -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractDataFlowAnalysisContext.ControlFlowGraph.get -> Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractDataFlowAnalysisContext.CopyAnalysisResultOpt.get -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.AbstractDataFlowAnalysisContext.ExceptionPathsAnalysis.get -> bool @@ -630,7 +631,7 @@ static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CacheBasedEquatable.opera static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis.CopyAbstractValue.Invalid.get -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis.CopyAbstractValue static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis.CopyAbstractValue.NotApplicable.get -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis.CopyAbstractValue static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis.CopyAbstractValue.Unknown.get -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis.CopyAbstractValue -static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis.CopyAnalysis.TryGetOrComputeResult(Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph cfg, Microsoft.CodeAnalysis.ISymbol owningSymbol, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.WellKnownTypeProvider wellKnownTypeProvider, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis = true, bool performPointsToAnalysis = true, bool exceptionPathsAnalysis = false) -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult +static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis.CopyAnalysis.TryGetOrComputeResult(Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph cfg, Microsoft.CodeAnalysis.ISymbol owningSymbol, Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions analyzerOptions, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.WellKnownTypeProvider wellKnownTypeProvider, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis = true, bool performPointsToAnalysis = true, bool exceptionPathsAnalysis = false) -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysis.Flow(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowOperationVisitor operationVisitor, Microsoft.CodeAnalysis.FlowAnalysis.BasicBlock block, TAnalysisData data) -> TAnalysisData static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysis.FlowBranch(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowOperationVisitor operationVisitor, Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowBranch branch, TAnalysisData data) -> TAnalysisData static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowOperationVisitor.EqualsHelper(System.Collections.Generic.IDictionary dict1, System.Collections.Generic.IDictionary dict2) -> bool @@ -648,8 +649,8 @@ static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAbs static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAbstractValue.Unknown.get -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAbstractValue static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAbstractValue.UnknownNotNull.get -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAbstractValue static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAbstractValue.UnknownNull.get -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAbstractValue -static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph cfg, Microsoft.CodeAnalysis.ISymbol owningSymbol, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.WellKnownTypeProvider wellKnownTypeProvider, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis = true, bool performCopyAnalysis = true, bool exceptionPathsAnalysis = false) -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysisResult -static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph cfg, Microsoft.CodeAnalysis.ISymbol owningSymbol, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.WellKnownTypeProvider wellKnownTypeProvider, out Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult copyAnalysisResultOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis = true, bool performCopyAnalysis = true, bool exceptionPathsAnalysis = false) -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysisResult +static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph cfg, Microsoft.CodeAnalysis.ISymbol owningSymbol, Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions analyzerOptions, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.WellKnownTypeProvider wellKnownTypeProvider, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis = true, bool performCopyAnalysis = true, bool exceptionPathsAnalysis = false) -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysisResult +static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph cfg, Microsoft.CodeAnalysis.ISymbol owningSymbol, Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions analyzerOptions, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.WellKnownTypeProvider wellKnownTypeProvider, out Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult copyAnalysisResultOpt, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis = true, bool performCopyAnalysis = true, bool exceptionPathsAnalysis = false) -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis.PointsToAnalysisResult static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PredicatedAnalysisData.EqualsHelper(Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DictionaryAnalysisData dict1, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DictionaryAnalysisData dict2) -> bool static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.SetAbstractDomain.Default.get -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.SetAbstractDomain static Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.ValueContentAnalysis.ValueContentAnalysis.TryGetOrComputeResult(Microsoft.CodeAnalysis.FlowAnalysis.ControlFlowGraph cfg, Microsoft.CodeAnalysis.ISymbol owningSymbol, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.WellKnownTypeProvider wellKnownTypeProvider, Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions analyzerOptions, Microsoft.CodeAnalysis.DiagnosticDescriptor rule, System.Threading.CancellationToken cancellationToken, Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisKind interproceduralAnalysisKind = Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.InterproceduralAnalysisKind.None, bool pessimisticAnalysis = true, bool performPointsToAnalysis = true) -> Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.DataFlowAnalysisResult diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs index 9fe509db42..1f2e04bf3c 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/Maintainability/AvoidDeadConditionalCode.cs @@ -56,6 +56,12 @@ public override void Initialize(AnalysisContext context) compilationContext.RegisterOperationBlockAction(operationBlockContext => { var owningSymbol = operationBlockContext.OwningSymbol; + if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockContext.Options, + AlwaysTrueFalseOrNullRule, operationBlockContext.Compilation, operationBlockContext.CancellationToken)) + { + return; + } + var processedOperationRoots = new HashSet(); foreach (var operationRoot in operationBlockContext.OperationBlocks) diff --git a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/ValidateArgumentsOfPublicMethods.cs b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/ValidateArgumentsOfPublicMethods.cs index eff264d499..0ad7b8f4bb 100644 --- a/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/ValidateArgumentsOfPublicMethods.cs +++ b/src/Microsoft.CodeQuality.Analyzers/Core/QualityGuidelines/ValidateArgumentsOfPublicMethods.cs @@ -44,7 +44,9 @@ public override void Initialize(AnalysisContext context) // Analyze externally visible methods with reference type parameters. if (!(operationBlockContext.OwningSymbol is IMethodSymbol containingMethod) || !containingMethod.IsExternallyVisible() || - !containingMethod.Parameters.Any(p => p.Type.IsReferenceType)) + !containingMethod.Parameters.Any(p => p.Type.IsReferenceType) || + containingMethod.IsConfiguredToSkipAnalysis(operationBlockContext.Options, + Rule, operationBlockContext.Compilation, operationBlockContext.CancellationToken)) { return; } diff --git a/src/Microsoft.CodeQuality.Analyzers/UnitTests/Maintainability/AvoidDeadConditionalCode_NullAnalysis.cs b/src/Microsoft.CodeQuality.Analyzers/UnitTests/Maintainability/AvoidDeadConditionalCode_NullAnalysis.cs index 6150fef89f..bd44b4eb61 100644 --- a/src/Microsoft.CodeQuality.Analyzers/UnitTests/Maintainability/AvoidDeadConditionalCode_NullAnalysis.cs +++ b/src/Microsoft.CodeQuality.Analyzers/UnitTests/Maintainability/AvoidDeadConditionalCode_NullAnalysis.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Test.Utilities; @@ -6569,5 +6571,56 @@ End Sub End Class ", validationMode: TestValidationMode.AllowCompileErrors); } + + [Trait(Traits.DataflowAnalysis, Traits.Dataflow.NullAnalysis)] + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality." + AvoidDeadConditionalCode.RuleId + ".excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = M1")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + // Test0.cs(7,13): warning CA1508: 'param == null' is always 'true'. Remove or refactor the condition(s) to avoid dead code. + GetCSharpResultAt(7, 13, @"param == null", "true") + }; + } + + VerifyCSharp(@" +class Test +{ + void M1(string param) + { + param = null; + if (param == null) + { + } + } +} +", GetEditorConfigAdditionalFile(editorConfigText), expected); + + expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + // Test0.vb(5,12): warning CA1508: 'param Is Nothing' is always 'True'. Remove or refactor the condition(s) to avoid dead code. + GetBasicResultAt(5, 12, "param Is Nothing", "True") + }; + } + + VerifyBasic(@" +Module Test + Sub M1(param As String) + param = Nothing + If param Is Nothing Then + End If + End Sub +End Module", GetEditorConfigAdditionalFile(editorConfigText), expected); + } } } diff --git a/src/Microsoft.CodeQuality.Analyzers/UnitTests/QualityGuidelines/ValidateArgumentsOfPublicMethodsTests.cs b/src/Microsoft.CodeQuality.Analyzers/UnitTests/QualityGuidelines/ValidateArgumentsOfPublicMethodsTests.cs index 5573aedeaf..89c77bdec7 100644 --- a/src/Microsoft.CodeQuality.Analyzers/UnitTests/QualityGuidelines/ValidateArgumentsOfPublicMethodsTests.cs +++ b/src/Microsoft.CodeQuality.Analyzers/UnitTests/QualityGuidelines/ValidateArgumentsOfPublicMethodsTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Test.Utilities; @@ -5961,5 +5962,51 @@ private static void Bar2(object input) } }"); } + + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality." + ValidateArgumentsOfPublicMethods.RuleId + ".excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = M1")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + // Test0.cs(6,17): warning CA1062: In externally visible method 'void Test.M1(string str)', validate parameter 'str' 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. + GetCSharpResultAt(6, 17, "void Test.M1(string str)", "str") + }; + } + + VerifyCSharp(@" +public class Test +{ + public void M1(string str) + { + var x = str.ToString(); + } +} +", GetEditorConfigAdditionalFile(editorConfigText), expected); + + expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + // Test0.vb(4,17): warning CA1062: In externally visible method 'Sub Test.M1(str As String)', validate parameter 'str' 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. + GetBasicResultAt(4, 17, "Sub Test.M1(str As String)", "str") + }; + } + + VerifyBasic(@" +Public Class Test + Public Sub M1(str As String) + Dim x = str.ToString() + End Sub +End Class +", GetEditorConfigAdditionalFile(editorConfigText), expected); + } } } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Data/ReviewSqlQueriesForSecurityVulnerabilities.cs b/src/Microsoft.NetCore.Analyzers/Core/Data/ReviewSqlQueriesForSecurityVulnerabilities.cs index 583344e9cb..df60930ceb 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Data/ReviewSqlQueriesForSecurityVulnerabilities.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Data/ReviewSqlQueriesForSecurityVulnerabilities.cs @@ -8,8 +8,6 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis; -using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.ValueContentAnalysis; namespace Microsoft.NetCore.Analyzers.Data @@ -57,6 +55,11 @@ public override void Initialize(AnalysisContext context) compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext => { ISymbol symbol = operationBlockStartContext.OwningSymbol; + if (symbol.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options, + Rule, operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken)) + { + return; + } var isInDbCommandConstructor = false; var isInDataAdapterConstructor = false; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs index 517f0bfda0..98378ba9a3 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposableFieldsShouldBeDisposed.cs @@ -126,7 +126,7 @@ void addOrUpdateFieldDisposedValue(IFieldSymbol field, bool disposed) var interproceduralAnalysisConfig = InterproceduralAnalysisConfiguration.Create( operationBlockStartContext.Options, Rule, InterproceduralAnalysisKind.None, operationBlockStartContext.CancellationToken); var pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult(cfg, - containingMethod, wellKnownTypeProvider, interproceduralAnalysisConfig, + containingMethod, operationBlockStartContext.Options, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis: false, performCopyAnalysis: false); if (pointsToAnalysisResult == null) @@ -234,7 +234,8 @@ bool ShouldAnalyze(INamedTypeSymbol namedType) // and have at least one disposable field. return !hasErrors && namedType.IsDisposable(disposeAnalysisHelper.IDisposable) && - !disposeAnalysisHelper.GetDisposableFields(namedType).IsEmpty; + !disposeAnalysisHelper.GetDisposableFields(namedType).IsEmpty && + !namedType.IsConfiguredToSkipAnalysis(compilationContext.Options, Rule, compilationContext.Compilation, compilationContext.CancellationToken); } bool IsDisposeMethod(IMethodSymbol method) diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs index bf6dd40b14..05343705a5 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs @@ -86,7 +86,9 @@ public override void Initialize(AnalysisContext context) compilationContext.RegisterOperationBlockAction(operationBlockContext => { if (!(operationBlockContext.OwningSymbol is IMethodSymbol containingMethod) || - !disposeAnalysisHelper.HasAnyDisposableCreationDescendant(operationBlockContext.OperationBlocks, containingMethod)) + !disposeAnalysisHelper.HasAnyDisposableCreationDescendant(operationBlockContext.OperationBlocks, containingMethod) || + containingMethod.IsConfiguredToSkipAnalysis(operationBlockContext.Options, + NotDisposedRule, operationBlockContext.Compilation, operationBlockContext.CancellationToken)) { return; } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs index 02631571af..62110667cc 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Runtime/DoNotPassLiteralsAsLocalizedParameters.cs @@ -60,7 +60,9 @@ public override void Initialize(AnalysisContext context) compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext => { - if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod)) + if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod) || + containingMethod.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options, + Rule, operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken)) { return; } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotAddArchiveItemPathToTheTargetFileSystemPath.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotAddArchiveItemPathToTheTargetFileSystemPath.cs index 4e7dc6d559..46602432e4 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotAddArchiveItemPathToTheTargetFileSystemPath.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotAddArchiveItemPathToTheTargetFileSystemPath.cs @@ -11,8 +11,10 @@ namespace Microsoft.NetCore.Analyzers.Security [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] public class DoNotAddArchiveItemPathToTheTargetFileSystemPath : SourceTriggeredTaintedDataAnalyzerBase { + internal const string RuleId = "CA5389"; + internal static DiagnosticDescriptor Rule = SecurityHelpers.CreateDiagnosticDescriptor( - "CA5389", + RuleId, typeof(MicrosoftNetCoreAnalyzersResources), nameof(MicrosoftNetCoreAnalyzersResources.DoNotAddArchiveItemPathToTheTargetFileSystemPath), nameof(MicrosoftNetCoreAnalyzersResources.DoNotAddArchiveItemPathToTheTargetFileSystemPathMessage), diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotInstallRootCert.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotInstallRootCert.cs index 757f84bc9e..c789ead36b 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotInstallRootCert.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotInstallRootCert.cs @@ -119,6 +119,17 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterOperationBlockStartAction( (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) => { + var owningSymbol = operationBlockStartAnalysisContext.OwningSymbol; + + // TODO: Handle case when exactly one of the below rules is configured to skip analysis. + if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + DefinitelyInstallRootCertRule, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && + owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + MaybeInstallRootCertRule, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) + { + return; + } + operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { @@ -168,6 +179,7 @@ public override void Initialize(AnalysisContext context) allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages( compilationAnalysisContext.Compilation, rootOperationsNeedingAnalysis, + compilationAnalysisContext.Options, WellKnownTypeNames.SystemSecurityCryptographyX509CertificatesX509Store, constructorMapper, PropertyMappers, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSetSwitch.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSetSwitch.cs index a303c5481e..fca10da13e 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSetSwitch.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotSetSwitch.cs @@ -94,6 +94,12 @@ public override void Initialize(AnalysisContext context) return; } + if (IsConfiguredToSkipAnalysis(DoNotDisableSchUseStrongCryptoRule, operationAnalysisContext) && + IsConfiguredToSkipAnalysis(DoNotDisableSpmSecurityProtocolsRule, operationAnalysisContext)) + { + return; + } + var values = invocationOperation.Arguments.Select(s => s.Value.ConstantValue).ToArray(); if (values[0].HasValue && @@ -101,7 +107,8 @@ public override void Initialize(AnalysisContext context) { if (values[0].Value is string switchName && BadSwitches.TryGetValue(switchName, out var pair) && - pair.BadValue.Equals(values[1].Value)) + pair.BadValue.Equals(values[1].Value) && + !IsConfiguredToSkipAnalysis(pair.Rule, operationAnalysisContext)) { operationAnalysisContext.ReportDiagnostic( invocationOperation.CreateDiagnostic( @@ -114,6 +121,7 @@ public override void Initialize(AnalysisContext context) var valueContentResult = ValueContentAnalysis.TryGetOrComputeResult( invocationOperation.GetEnclosingControlFlowGraph(), operationAnalysisContext.ContainingSymbol, + operationAnalysisContext.Options, wellKnownTypeProvider, InterproceduralAnalysisConfiguration.Create( operationAnalysisContext.Options, @@ -134,7 +142,8 @@ public override void Initialize(AnalysisContext context) if (switchNameValueContent.TryGetSingleLiteral(out var switchName) && switchValueValueContent.TryGetSingleLiteral(out var switchValue) && BadSwitches.TryGetValue(switchName, out var pair) && - pair.BadValue.Equals(switchValue)) + pair.BadValue.Equals(switchValue) && + !IsConfiguredToSkipAnalysis(pair.Rule, operationAnalysisContext)) { operationAnalysisContext.ReportDiagnostic( invocationOperation.CreateDiagnostic( @@ -146,5 +155,8 @@ public override void Initialize(AnalysisContext context) OperationKind.Invocation); }); } + + static bool IsConfiguredToSkipAnalysis(DiagnosticDescriptor rule, OperationAnalysisContext context) + => context.ContainingSymbol.IsConfiguredToSkipAnalysis(context.Options, rule, context.Compilation, context.CancellationToken); } } diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDSA.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDSA.cs index 6e976685c8..c6c70862b6 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDSA.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseDSA.cs @@ -38,7 +38,7 @@ public sealed class DoNotUseDSA : DiagnosticAnalyzer isEnabledByDefault: DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX, description: s_Description, helpLinkUri: null, - customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); + customTags: WellKnownDiagnosticTags.Telemetry); private static readonly ImmutableHashSet s_DSAAlgorithmNames = ImmutableHashSet.Create( diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerBinaryFormatterWithoutBinder.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerBinaryFormatterWithoutBinder.cs index 2b52fdcbd7..11ebd11e4c 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerBinaryFormatterWithoutBinder.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerBinaryFormatterWithoutBinder.cs @@ -22,14 +22,16 @@ public class DoNotUseInsecureDeserializerBinaryFormatterWithoutBinder : DoNotUse nameof(MicrosoftNetCoreAnalyzersResources.BinaryFormatterDeserializeWithoutBinderSetTitle), nameof(MicrosoftNetCoreAnalyzersResources.BinaryFormatterDeserializeWithoutBinderSetMessage), isEnabledByDefault: false, - helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2301-do-not-call-binaryformatter-deserialize-without-first-setting-binaryformatter-binder"); + helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2301-do-not-call-binaryformatter-deserialize-without-first-setting-binaryformatter-binder", + customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); internal static readonly DiagnosticDescriptor RealBinderMaybeNotSetDescriptor = SecurityHelpers.CreateDiagnosticDescriptor( "CA2302", nameof(MicrosoftNetCoreAnalyzersResources.BinaryFormatterDeserializeMaybeWithoutBinderSetTitle), nameof(MicrosoftNetCoreAnalyzersResources.BinaryFormatterDeserializeMaybeWithoutBinderSetMessage), isEnabledByDefault: false, - helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2302-ensure-binaryformatter-binder-is-set-before-calling-binaryformatter-deserialize"); + helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2302-ensure-binaryformatter-binder-is-set-before-calling-binaryformatter-deserialize", + customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); protected override string DeserializerTypeMetadataName => WellKnownTypeNames.SystemRuntimeSerializationFormattersBinaryBinaryFormatter; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolver.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolver.cs index 00bfa7d927..22966e1703 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolver.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolver.cs @@ -31,14 +31,16 @@ class DoNotUseInsecureDeserializerJavaScriptSerializerWithSimpleTypeResolver : D nameof(MicrosoftNetCoreAnalyzersResources.JavaScriptSerializerWithSimpleTypeResolverTitle), nameof(MicrosoftNetCoreAnalyzersResources.JavaScriptSerializerWithSimpleTypeResolverMessage), isEnabledByDefault: false, - helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2321"); + helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2321", + customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); internal static readonly DiagnosticDescriptor MaybeWithSimpleTypeResolver = SecurityHelpers.CreateDiagnosticDescriptor( "CA2322", nameof(MicrosoftNetCoreAnalyzersResources.JavaScriptSerializerMaybeWithSimpleTypeResolverTitle), nameof(MicrosoftNetCoreAnalyzersResources.JavaScriptSerializerMaybeWithSimpleTypeResolverMessage), isEnabledByDefault: false, - helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2322"); + helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2322", + customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create( @@ -151,6 +153,17 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterOperationBlockStartAction( (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) => { + var owningSymbol = operationBlockStartAnalysisContext.OwningSymbol; + + // TODO: Handle case when exactly one of the below rules is configured to skip analysis. + if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + DefinitelyWithSimpleTypeResolver, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && + owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + MaybeWithSimpleTypeResolver, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) + { + return; + } + operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { @@ -202,6 +215,7 @@ public override void Initialize(AnalysisContext context) allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages( compilationAnalysisContext.Compilation, rootOperationsNeedingAnalysis, + compilationAnalysisContext.Options, WellKnownTypeNames.SystemWebScriptSerializationJavaScriptSerializer, constructorMapper, PropertyMappers, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerNetDataContractSerializerWithoutBinder.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerNetDataContractSerializerWithoutBinder.cs index 1b1c28282d..0560d17999 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerNetDataContractSerializerWithoutBinder.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerNetDataContractSerializerWithoutBinder.cs @@ -22,14 +22,16 @@ public class DoNotUseInsecureDeserializerNetDataContractSerializerWithoutBinder nameof(MicrosoftNetCoreAnalyzersResources.NetDataContractSerializerDeserializeWithoutBinderSetTitle), nameof(MicrosoftNetCoreAnalyzersResources.NetDataContractSerializerDeserializeWithoutBinderSetMessage), isEnabledByDefault: false, - helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2311-do-not-deserialize-without-first-setting-netdatacontractserializer-binder"); + helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2311-do-not-deserialize-without-first-setting-netdatacontractserializer-binder", + customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); internal static readonly DiagnosticDescriptor RealBinderMaybeNotSetDescriptor = SecurityHelpers.CreateDiagnosticDescriptor( "CA2312", nameof(MicrosoftNetCoreAnalyzersResources.NetDataContractSerializerDeserializeMaybeWithoutBinderSetTitle), nameof(MicrosoftNetCoreAnalyzersResources.NetDataContractSerializerDeserializeMaybeWithoutBinderSetMessage), isEnabledByDefault: false, - helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2312-ensure-netdatacontractserializer-binder-is-set-before-deserializing"); + helpLinkUri: "https://docs.microsoft.com/visualstudio/code-quality/ca2312-ensure-netdatacontractserializer-binder-is-set-before-deserializing", + customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); protected override string DeserializerTypeMetadataName => WellKnownTypeNames.SystemRuntimeSerializationNetDataContractSerializer; diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerWithoutBinderBase.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerWithoutBinderBase.cs index 7dd0f4b6b8..eab6073cab 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerWithoutBinderBase.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureDeserializerWithoutBinderBase.cs @@ -114,6 +114,17 @@ public sealed override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterOperationBlockStartAction( (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) => { + var owningSymbol = operationBlockStartAnalysisContext.OwningSymbol; + + // TODO: Handle case when exactly one of the below rules is configured to skip analysis. + if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + BinderDefinitelyNotSetDescriptor, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && + owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + BinderMaybeNotSetDescriptor, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) + { + return; + } + operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { @@ -179,6 +190,7 @@ public sealed override void Initialize(AnalysisContext context) allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages( compilationAnalysisContext.Compilation, rootOperationsNeedingAnalysis, + compilationAnalysisContext.Options, this.DeserializerTypeMetadataName, DoNotUseInsecureDeserializerWithoutBinderBase.ConstructorMapper, propertyMappers, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureSettingsForJsonNet.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureSettingsForJsonNet.cs index ba188fff65..f97d2b293d 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureSettingsForJsonNet.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseInsecureSettingsForJsonNet.cs @@ -33,14 +33,16 @@ public sealed class DoNotUseInsecureSettingsForJsonNet : DiagnosticAnalyzer nameof(MicrosoftNetCoreAnalyzersResources.JsonNetInsecureSettingsTitle), nameof(MicrosoftNetCoreAnalyzersResources.JsonNetInsecureSettingsMessage), isEnabledByDefault: false, - helpLinkUri: null); + helpLinkUri: null, + customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); internal static readonly DiagnosticDescriptor MaybeInsecureSettings = SecurityHelpers.CreateDiagnosticDescriptor( "CA2328", nameof(MicrosoftNetCoreAnalyzersResources.JsonNetMaybeInsecureSettingsTitle), nameof(MicrosoftNetCoreAnalyzersResources.JsonNetMaybeInsecureSettingsMessage), isEnabledByDefault: false, - helpLinkUri: null); + helpLinkUri: null, + customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create( @@ -138,6 +140,17 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterOperationBlockStartAction( (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) => { + var owningSymbol = operationBlockStartAnalysisContext.OwningSymbol; + + // TODO: Handle case when exactly one of the below rules is configured to skip analysis. + if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + DefinitelyInsecureSettings, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && + owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + MaybeInsecureSettings, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) + { + return; + } + operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { @@ -207,6 +220,7 @@ public override void Initialize(AnalysisContext context) allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages( compilationAnalysisContext.Compilation, rootOperationsNeedingAnalysis, + compilationAnalysisContext.Options, WellKnownTypeNames.NewtonsoftJsonJsonSerializerSettings, ConstructorMapper, PropertyMappers, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFInsufficientIterationCount.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFInsufficientIterationCount.cs index b4424d2982..0f98274c67 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFInsufficientIterationCount.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/DoNotUseWeakKDFInsufficientIterationCount.cs @@ -117,6 +117,15 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterOperationBlockStartAction( (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) => { + // TODO: Handle case when exactly one of the below rules is configured to skip analysis. + if (operationBlockStartAnalysisContext.OwningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + DefinitelyUseWeakKDFInsufficientIterationCountRule, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && + operationBlockStartAnalysisContext.OwningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + MaybeUseWeakKDFInsufficientIterationCountRule, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) + { + return; + } + operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { @@ -131,7 +140,7 @@ public override void Initialize(AnalysisContext context) } } }, - OperationKind.Invocation); + OperationKind.Invocation); operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => @@ -166,6 +175,7 @@ public override void Initialize(AnalysisContext context) allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages( compilationAnalysisContext.Compilation, rootOperationsNeedingAnalysis, + compilationAnalysisContext.Options, WellKnownTypeNames.SystemSecurityCryptographyRfc2898DeriveBytes, constructorMapper, propertyMappers, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/SourceTriggeredTaintedDataAnalyzerBase.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/SourceTriggeredTaintedDataAnalyzerBase.cs index 8558f6733e..3c1bb13978 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/SourceTriggeredTaintedDataAnalyzerBase.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/SourceTriggeredTaintedDataAnalyzerBase.cs @@ -64,6 +64,12 @@ public override void Initialize(AnalysisContext context) operationBlockStartContext => { ISymbol owningSymbol = operationBlockStartContext.OwningSymbol; + if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options, + TaintedDataEnteringSinkDescriptor, operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken)) + { + return; + } + PooledHashSet rootOperationsNeedingAnalysis = PooledHashSet.GetInstance(); operationBlockStartContext.RegisterOperationAction( @@ -102,6 +108,7 @@ public override void Initialize(AnalysisContext context) pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( rootOperation.GetEnclosingControlFlowGraph(), owningSymbol, + operationAnalysisContext.Options, WellKnownTypeProvider.GetOrCreate(operationAnalysisContext.Compilation), InterproceduralAnalysisConfiguration.Create( operationAnalysisContext.Options, @@ -131,6 +138,7 @@ public override void Initialize(AnalysisContext context) valueContentAnalysisResultOpt = ValueContentAnalysis.TryGetOrComputeResult( rootOperation.GetEnclosingControlFlowGraph(), owningSymbol, + operationAnalysisContext.Options, WellKnownTypeProvider.GetOrCreate(operationAnalysisContext.Compilation), InterproceduralAnalysisConfiguration.Create( operationAnalysisContext.Options, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseContainerLevelAccessPolicy.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseContainerLevelAccessPolicy.cs index 0d00e7af3b..4ecb09ddd2 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseContainerLevelAccessPolicy.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseContainerLevelAccessPolicy.cs @@ -104,6 +104,11 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterOperationBlockStartAction(operationBlockStartContext => { var owningSymbol = operationBlockStartContext.OwningSymbol; + if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options, + Rule, operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken)) + { + return; + } operationBlockStartContext.RegisterOperationAction(operationAnalysisContext => { @@ -142,6 +147,7 @@ public override void Initialize(AnalysisContext context) var pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( invocationOperation.GetTopmostParentBlock().GetEnclosingControlFlowGraph(), owningSymbol, + operationBlockStartContext.Options, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseRSAWithSufficientKeySize.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseRSAWithSufficientKeySize.cs index 59473736ec..ee28b9b87b 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseRSAWithSufficientKeySize.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseRSAWithSufficientKeySize.cs @@ -38,7 +38,7 @@ public sealed class UseRSAWithSufficientKeySize : DiagnosticAnalyzer isEnabledByDefault: DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX, description: s_Description, helpLinkUri: null, - customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); + customTags: WellKnownDiagnosticTags.Telemetry); private static readonly ImmutableHashSet s_RSAAlgorithmNames = ImmutableHashSet.Create( diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseSecureCookiesASPNetCore.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseSecureCookiesASPNetCore.cs index ecf6d134cf..16b987191e 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseSecureCookiesASPNetCore.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseSecureCookiesASPNetCore.cs @@ -105,6 +105,15 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterOperationBlockStartAction( (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) => { + // TODO: Handle case when exactly one of the below rules is configured to skip analysis. + if (operationBlockStartAnalysisContext.OwningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + DefinitelyUseSecureCookiesASPNetCoreRule, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && + operationBlockStartAnalysisContext.OwningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, + MaybeUseSecureCookiesASPNetCoreRule, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) + { + return; + } + operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { @@ -165,6 +174,7 @@ public override void Initialize(AnalysisContext context) allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages( compilationAnalysisContext.Compilation, rootOperationsNeedingAnalysis, + compilationAnalysisContext.Options, WellKnownTypeNames.MicrosoftAspNetCoreHttpCookieOptions, constructorMapper, PropertyMappers, diff --git a/src/Microsoft.NetCore.Analyzers/Core/Security/UseSharedAccessProtocolHttpsOnly.cs b/src/Microsoft.NetCore.Analyzers/Core/Security/UseSharedAccessProtocolHttpsOnly.cs index 5daf76688c..169633a51d 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Security/UseSharedAccessProtocolHttpsOnly.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Security/UseSharedAccessProtocolHttpsOnly.cs @@ -89,6 +89,11 @@ public override void Initialize(AnalysisContext context) compilationStartAnalysisContext.RegisterOperationBlockStartAction(operationBlockStartContext => { var owningSymbol = operationBlockStartContext.OwningSymbol; + if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options, Rule, + operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken)) + { + return; + } operationBlockStartContext.RegisterOperationAction(operationAnalysisContext => { @@ -139,6 +144,7 @@ s.Parameter.Type is INamedTypeSymbol namedTypeSymbol && var valueContentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( invocationOperation.GetTopmostParentBlock().GetEnclosingControlFlowGraph(), owningSymbol, + operationAnalysisContext.Options, wellKnownTypeProvider, interproceduralAnalysisConfig, out var copyAnalysisResult, diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Data/ReviewSQLQueriesForSecurityVulnerabilitiesTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Data/ReviewSQLQueriesForSecurityVulnerabilitiesTests.cs index ac32d89e36..2091b445af 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Data/ReviewSQLQueriesForSecurityVulnerabilitiesTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Data/ReviewSQLQueriesForSecurityVulnerabilitiesTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Test.Utilities; @@ -1620,5 +1621,57 @@ protected void Page_Load(object sender, EventArgs e) ", GetCSharpResultAt(102, 21, "string Command.CommandText", "Page_Load")); } + + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality." + ReviewSqlQueriesForSecurityVulnerabilities.RuleId + ".excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = M1")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(92, 9, "string Command.CommandText", "M1") + }; + } + + VerifyCSharp($@" +{SetupCodeCSharp} + +class Test +{{ + void M1(string param) + {{ + Command c = new Command(); + var str = param; + c.CommandText = str; + }} +}}", GetEditorConfigAdditionalFile(editorConfigText), expected); + + expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetBasicResultAt(128, 9, "Property Command.CommandText As String", "M1") + }; + } + + VerifyBasic($@" +{SetupCodeBasic} + +Module Test + Sub M1(param As String) + Dim c As New Command() + Dim str As String = param + c.CommandText = str + End Sub +End Module", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + + } } diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DisposableFieldsShouldBeDisposedTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DisposableFieldsShouldBeDisposedTests.cs index 55e4511cdb..125ed573d8 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DisposableFieldsShouldBeDisposedTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DisposableFieldsShouldBeDisposedTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Test.Utilities; @@ -2842,5 +2843,78 @@ protected override void DisposeUnderLock() } "); } + + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = B")] + [InlineData("dotnet_code_quality." + DisposableFieldsShouldBeDisposed.RuleId + ".excluded_symbol_names = B")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = B")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + // Test0.cs(13,24): warning CA2213: 'B' contains field 'a' that is of IDisposable type 'A', but it is never disposed. Change the Dispose method on 'B' to call Dispose or Close on this field. + GetCSharpResultAt(13, 24, "B", "a", "A") + }; + } + + VerifyCSharp(@" +using System; + +class A : IDisposable +{ + public void Dispose() + { + } +} + +class B : IDisposable +{ + private readonly A a; + public B() + { + a = new A(); + } + + public void Dispose() + { + } +} +", GetEditorConfigAdditionalFile(editorConfigText), expected); + + expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + // Test0.vb(13,22): warning CA2213: 'B' contains field 'a' that is of IDisposable type 'A', but it is never disposed. Change the Dispose method on 'B' to call Dispose or Close on this field. + GetBasicResultAt(13, 22, "B", "a", "A") + }; + } + + VerifyBasic(@" +Imports System + +Class A + Implements IDisposable + Public Sub Dispose() Implements IDisposable.Dispose + End Sub +End Class + +Class B + Implements IDisposable + + Private ReadOnly a As A + Sub New() + a = New A() + End Sub + + Public Sub Dispose() Implements IDisposable.Dispose + End Sub +End Class", GetEditorConfigAdditionalFile(editorConfigText), expected); + } } } diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DisposeObjectsBeforeLosingScopeTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DisposeObjectsBeforeLosingScopeTests.cs index 324bd7a73e..4ec25c89bc 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DisposeObjectsBeforeLosingScopeTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DisposeObjectsBeforeLosingScopeTests.cs @@ -10814,5 +10814,136 @@ public async Task M() // Test0.cs(11,30): warning CA2000: Call System.IDisposable.Dispose on object created by 'GetStreamAsync()' before all references to it are out of scope. GetCSharpResultAt(11, 30, "GetStreamAsync()")); } + + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality." + DisposeObjectsBeforeLosingScope.RuleId + ".excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = M1")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + // Test0.cs(15,17): warning CA2000: Call System.IDisposable.Dispose on object created by 'new A()' before all references to it are out of scope. + GetCSharpResultAt(15, 17, "new A()") + }; + } + + VerifyCSharp(@" +using System; + +class A : IDisposable +{ + public void Dispose() + { + } +} + +class Test +{ + void M1() + { + var a = new A(); + } +} +", GetEditorConfigAdditionalFile(editorConfigText), expected); + + expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + // Test0.vb(12,18): warning CA2000: Call System.IDisposable.Dispose on object created by 'New A()' before all references to it are out of scope. + GetBasicResultAt(12, 18, "New A()") + }; + } + + VerifyBasic(@" +Imports System + +Class A + Implements IDisposable + Public Sub Dispose() Implements IDisposable.Dispose + End Sub +End Class + +Class Test + Sub M1() + Dim a As New A() + End Sub +End Class", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = M2")] + [InlineData("dotnet_code_quality.interproceduraldataflow.excluded_symbol_names = M2")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption_InterproceduralDataflow(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length > 0) + { + expected = new DiagnosticResult[] + { + // Test0.cs(15,17): warning CA2000: Call System.IDisposable.Dispose on object created by 'new A()' before all references to it are out of scope. + GetCSharpResultAt(15, 17, "new A()") + }; + } + + VerifyCSharp(@" +using System; + +class A : IDisposable +{ + public void Dispose() + { + } +} + +class Test +{ + void M1() + { + var a = new A(); + M2(a); + } + + void M2(A a) => a.Dispose(); +} +", GetEditorConfigAdditionalFile(editorConfigText), expected); + + expected = Array.Empty(); + if (editorConfigText.Length > 0) + { + expected = new DiagnosticResult[] + { + // Test0.vb(12,18): warning CA2000: Call System.IDisposable.Dispose on object created by 'New A()' before all references to it are out of scope. + GetBasicResultAt(12, 18, "New A()") + }; + } + + VerifyBasic(@" +Imports System + +Class A + Implements IDisposable + Public Sub Dispose() Implements IDisposable.Dispose + End Sub +End Class + +Class Test + Sub M1() + Dim a As New A() + M2(a) + End Sub + + Sub M2(a As A) + a.Dispose() + End Sub +End Class", GetEditorConfigAdditionalFile(editorConfigText), expected); + } } } diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DoNotPassLiteralsAsLocalizedParametersTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DoNotPassLiteralsAsLocalizedParametersTests.cs index 16d602028d..8fe7e82446 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DoNotPassLiteralsAsLocalizedParametersTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Runtime/DoNotPassLiteralsAsLocalizedParametersTests.cs @@ -1517,6 +1517,42 @@ public void ShouldBeLocalized_SubTypesExcludedByConfiguration_NoDiagnostic(strin VerifyCSharp(@" using System; +public class Test +{ + public void M1() + { + var str = ""a""; + var x = new Exception(str); + var y = new ArgumentException(str); + var z = new InvalidOperationException(str); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality." + DoNotPassLiteralsAsLocalizedParameters.RuleId + ".excluded_symbol_names = M1")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = M1")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (string.IsNullOrEmpty(editorConfigText)) + { + expected = new[] + { + // Test0.cs(9,31): warning CA1303: Method 'void Test.M1()' passes a literal string as parameter 'message' of a call to 'Exception.Exception(string message)'. Retrieve the following string(s) from a resource table instead: "a". + GetCSharpResultAt(9, 31, "void Test.M1()", "message", "Exception.Exception(string message)", "a"), + // Test0.cs(10,39): warning CA1303: Method 'void Test.M1()' passes a literal string as parameter 'message' of a call to 'ArgumentException.ArgumentException(string message)'. Retrieve the following string(s) from a resource table instead: "a". + GetCSharpResultAt(10, 39, "void Test.M1()", "message", "ArgumentException.ArgumentException(string message)", "a"), + // Test0.cs(11,47): warning CA1303: Method 'void Test.M1()' passes a literal string as parameter 'message' of a call to 'InvalidOperationException.InvalidOperationException(string message)'. Retrieve the following string(s) from a resource table instead: "a". + GetCSharpResultAt(11, 47, "void Test.M1()", "message", "InvalidOperationException.InvalidOperationException(string message)", "a") + }; + } + + VerifyCSharp(@" +using System; + public class Test { public void M1() diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotAddArchiveItemPathToTheTargetFileSystemPathTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotAddArchiveItemPathToTheTargetFileSystemPathTests.cs index 584718a54c..c9f740b548 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotAddArchiveItemPathToTheTargetFileSystemPathTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotAddArchiveItemPathToTheTargetFileSystemPathTests.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Xunit; using Xunit.Abstractions; @@ -206,6 +208,34 @@ public void TestMethod(ZipArchiveEntry zipArchiveEntry) }"); } + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality." + DoNotAddArchiveItemPathToTheTargetFileSystemPath.RuleId + ".excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = TestMethod")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(8, 9, 8, 39, "void ZipFileExtensions.ExtractToFile(ZipArchiveEntry source, string destinationFileName)", "void TestClass.TestMethod(ZipArchiveEntry zipArchiveEntry)", "string ZipArchiveEntry.FullName", "void TestClass.TestMethod(ZipArchiveEntry zipArchiveEntry)") + }; + } + + VerifyCSharpWithDependencies(@" +using System.IO.Compression; + +class TestClass +{ + public void TestMethod(ZipArchiveEntry zipArchiveEntry) + { + zipArchiveEntry.ExtractToFile(zipArchiveEntry.FullName); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { return new DoNotAddArchiveItemPathToTheTargetFileSystemPath(); diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotDisableSchUseStrongCryptoTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotDisableSchUseStrongCryptoTests.cs index 3bf5cc9079..56d2b7c864 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotDisableSchUseStrongCryptoTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotDisableSchUseStrongCryptoTests.cs @@ -6,6 +6,7 @@ using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; @@ -232,6 +233,34 @@ public void TestMethod() }"); } + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality.CA5361.excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = TestMethod")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(8, 9, DoNotSetSwitch.DoNotDisableSchUseStrongCryptoRule, "SetSwitch") + }; + } + + VerifyCSharp(@" +using System; + +class TestClass +{ + public void TestMethod() + { + AppContext.SetSwitch(""Switch.System.Net.DontEnableSchUseStrongCrypto"", true); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { return new DoNotSetSwitch(); diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotDisableUsingServicePointManagerSecurityProtocolsTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotDisableUsingServicePointManagerSecurityProtocolsTests.cs index 3123d9d36a..69c7b0a6ae 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotDisableUsingServicePointManagerSecurityProtocolsTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotDisableUsingServicePointManagerSecurityProtocolsTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; @@ -227,6 +229,35 @@ public void TestMethod() }"); } + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = ExampleMethod")] + [InlineData("dotnet_code_quality.CA5378.excluded_symbol_names = ExampleMethod")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = ExampleMethod")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(9, 9, DoNotSetSwitch.DoNotDisableSpmSecurityProtocolsRule, "SetSwitch") + }; + } + + VerifyCSharp(@" +using System; + +public class ExampleClass +{ + public void ExampleMethod() + { + // CA5378 violation + AppContext.SetSwitch(""Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols"", true); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { return new DoNotSetSwitch(); diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotInstallRootCertTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotInstallRootCertTests.cs index 0f014dbd40..1f05d92125 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotInstallRootCertTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotInstallRootCertTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; @@ -405,6 +407,37 @@ public X509Store GetX509Store() }"); } + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = TestMethod")] + [InlineData(@"dotnet_code_quality.CA5380.excluded_symbol_names = TestMethod + dotnet_code_quality.CA5381.excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = TestMethod")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(10, 9, DoNotInstallRootCert.DefinitelyInstallRootCertRule) + }; + } + + VerifyCSharp(@" +using System.Security.Cryptography.X509Certificates; + +class TestClass +{ + public void TestMethod() + { + var storeName = StoreName.Root; + var x509Store = new X509Store(storeName); + x509Store.Add(new X509Certificate2()); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { return new DoNotInstallRootCert(); diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureDeserializerBinaryFormatterWithoutBinderTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureDeserializerBinaryFormatterWithoutBinderTests.cs index ef0a2199b1..1c3e33d58d 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureDeserializerBinaryFormatterWithoutBinderTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureDeserializerBinaryFormatterWithoutBinderTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; @@ -1144,5 +1145,56 @@ private object DoDeserialization(BinaryFormatter formatter, Stream stream) }", GetCSharpResultAt(21, 20, BinderNotSetRule, "object BinaryFormatter.Deserialize(Stream serializationStream)")); } + + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = DeserializeBookRecord")] + [InlineData(@"dotnet_code_quality.CA2301.excluded_symbol_names = DeserializeBookRecord + dotnet_code_quality.CA2302.excluded_symbol_names = DeserializeBookRecord")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = DeserializeBookRecord")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(29, 33, BinderNotSetRule, "object BinaryFormatter.Deserialize(Stream serializationStream)") + }; + } + + VerifyCSharp(@" +using System; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; + +[Serializable] +public class BookRecord +{ + public string Title { get; set; } + public string Author { get; set; } + public int PageCount { get; set; } + public AisleLocation Location { get; set; } +} + +[Serializable] +public class AisleLocation +{ + public char Aisle { get; set; } + public byte Shelf { get; set; } +} + +public class ExampleClass +{ + public BookRecord DeserializeBookRecord(byte[] bytes) + { + BinaryFormatter formatter = new BinaryFormatter(); + using (MemoryStream ms = new MemoryStream(bytes)) + { + return (BookRecord) formatter.Deserialize(ms); + } + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } } } diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolverTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolverTests.cs index d9e7bc3dd5..e955f0c11e 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolverTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureDeserializerJavascriptSerializerWithSimpleTypeResolverTests.cs @@ -1,7 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; @@ -600,5 +602,39 @@ public override string ResolveTypeId(Type type) }", GetCSharpResultAt(19, 20, MaybeRule, "object JavaScriptSerializer.DeserializeObject(string input)")); } + + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = D")] + [InlineData(@"dotnet_code_quality.CA2321.excluded_symbol_names = D + dotnet_code_quality.CA2322.excluded_symbol_names = D")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = D")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(12, 20, DefinitelyRule, "T JavaScriptSerializer.Deserialize(string input)") + }; + } + + VerifyCSharp(@" +using System.IO; +using System.Web.Script.Serialization; + +namespace Blah +{ + public class Program + { + public T D(string str) + { + JavaScriptSerializer s = new JavaScriptSerializer(new SimpleTypeResolver()); + return s.Deserialize(str); + } + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } } } diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureSettingsForJsonNetTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureSettingsForJsonNetTests.cs index 894ecae19f..d356450a34 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureSettingsForJsonNetTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseInsecureSettingsForJsonNetTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis; @@ -711,6 +712,37 @@ public JsonSerializerSettings GetSerializerSettings(bool flag) GetCSharpResultAt(19, 16, DefinitelyRule)); } + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = Method")] + [InlineData(@"dotnet_code_quality.CA2327.excluded_symbol_names = Method + dotnet_code_quality.CA2328.excluded_symbol_names = Method")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = Method")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(10, 16, DefinitelyRule) + }; + } + + this.VerifyCSharpWithJsonNet(@" +using Newtonsoft.Json; + +class Blah +{ + object Method(string s) + { + JsonSerializerSettings settings = new JsonSerializerSettings(); + settings.TypeNameHandling = TypeNameHandling.All; + return JsonConvert.DeserializeObject(s, settings); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { return new DoNotUseInsecureSettingsForJsonNet(); @@ -725,5 +757,10 @@ private void VerifyCSharpWithJsonNet(string source, params DiagnosticResult[] ex { this.VerifyCSharpAcrossTwoAssemblies(NewtonsoftJsonNetApis.CSharp, source, expected); } + + private void VerifyCSharpWithJsonNet(string source, FileAndSource additionalFile, params DiagnosticResult[] expected) + { + this.VerifyCSharpAcrossTwoAssemblies(NewtonsoftJsonNetApis.CSharp, source, additionalFile, expected); + } } } diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseWeakKDFInsufficientIterationCountTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseWeakKDFInsufficientIterationCountTests.cs index 6d786ca1a5..1e2b65c962 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseWeakKDFInsufficientIterationCountTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/DoNotUseWeakKDFInsufficientIterationCountTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; using Test.Utilities; using Xunit; @@ -359,6 +361,37 @@ public void TestMethod(byte[] password, byte[] salt, int iterations, int cb) }"); } + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = TestMethod")] + [InlineData(@"dotnet_code_quality.CA5387.excluded_symbol_names = TestMethod + dotnet_code_quality.CA5388.excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = TestMethod")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(10, 9, DoNotUseWeakKDFInsufficientIterationCount.DefinitelyUseWeakKDFInsufficientIterationCountRule, SufficientIterationCount) + }; + } + + VerifyCSharp(@" +using System.Security.Cryptography; + +class TestClass +{ + public void TestMethod(string password, byte[] salt, int cb) + { + var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt); + rfc2898DeriveBytes.IterationCount = 100; + rfc2898DeriveBytes.GetBytes(cb); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { return new DoNotUseWeakKDFInsufficientIterationCount(); diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/TaintedDataAnalyzerTestBase.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/TaintedDataAnalyzerTestBase.cs index 6668811e62..41b97a150f 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/TaintedDataAnalyzerTestBase.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/TaintedDataAnalyzerTestBase.cs @@ -47,6 +47,17 @@ protected void VerifyCSharpWithDependencies(string source, params DiagnosticResu this.VerifyCSharp(sources, ReferenceFlags.AddTestReferenceAssembly, expected); } + protected void VerifyCSharpWithDependencies(string source, FileAndSource additionalFile, params DiagnosticResult[] expected) + { + string[] sources = new string[] { source }; + if (this.AdditionalCSharpSources != null) + { + sources = sources.Concat(this.AdditionalCSharpSources).ToArray(); + } + + this.VerifyCSharp(sources, additionalFile, ReferenceFlags.AddTestReferenceAssembly, expected); + } + protected DiagnosticResult GetBasicResultAt(int sinkLine, int sinkColumn, int sourceLine, int sourceColumn, string sink, string sinkContainingMethod, string source, string sourceContainingMethod) { return GetBasicResultAt( diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseContainerLevelAccessPolicyTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseContainerLevelAccessPolicyTests.cs index 657834cb10..2f59a21c69 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseContainerLevelAccessPolicyTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseContainerLevelAccessPolicyTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Test.Utilities; @@ -9,9 +10,7 @@ namespace Microsoft.NetCore.Analyzers.Security.UnitTests { public class UseContainerLevelAccessPolicyTests : DiagnosticAnalyzerTestBase { - protected void VerifyCSharpWithDependencies(string source, params DiagnosticResult[] expected) - { - string microsoftWindowsAzureStorageCSharpSourceCode = @" + private const string MicrosoftWindowsAzureStorageCSharpSourceCode = @" using System; namespace Microsoft.WindowsAzure.Storage @@ -125,8 +124,20 @@ public sealed class SharedAccessTablePolicy } } }"; + + protected void VerifyCSharpWithDependencies(string source, params DiagnosticResult[] expected) + { this.VerifyCSharp( - new[] { source, microsoftWindowsAzureStorageCSharpSourceCode }.ToFileAndSource(), + new[] { source, MicrosoftWindowsAzureStorageCSharpSourceCode }.ToFileAndSource(), + expected); + } + + protected void VerifyCSharpWithDependencies(string source, FileAndSource additionalFile, params DiagnosticResult[] expected) + { + this.VerifyCSharp( + new[] { source, MicrosoftWindowsAzureStorageCSharpSourceCode }, + additionalFile, + ReferenceFlags.None, expected); } @@ -376,6 +387,37 @@ public void TestMethod(SharedAccessTablePolicy policy, string startPartitionKey, }"); } + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality." + UseContainerLevelAccessPolicy.DiagnosticId + ".excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = TestMethod")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(11, 9, UseContainerLevelAccessPolicy.Rule) + }; + } + + VerifyCSharpWithDependencies(@" +using System; +using Microsoft.WindowsAzure.Storage.Table; + +class TestClass +{ + public void TestMethod(SharedAccessTablePolicy policy, string startPartitionKey, string startRowKey, string endPartitionKey, string endRowKey) + { + var cloudTable = new CloudTable(); + string accessPolicyIdentifier = null; + cloudTable.GetSharedAccessSignature(policy, accessPolicyIdentifier, startPartitionKey, startRowKey, endPartitionKey, endRowKey); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { return new UseContainerLevelAccessPolicy(); diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseSecureCookiesASPNetCoreTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseSecureCookiesASPNetCoreTests.cs index c9540fd0e0..fc018126b4 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseSecureCookiesASPNetCoreTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseSecureCookiesASPNetCoreTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Test.Utilities; @@ -9,9 +10,7 @@ namespace Microsoft.NetCore.Analyzers.Security.UnitTests { public class UseSecureCookiesASPNetCoreTests : DiagnosticAnalyzerTestBase { - protected void VerifyCSharpWithDependencies(string source, params DiagnosticResult[] expected) - { - string microsoftAspNetCoreHttpNamespaceCSharpSourceCode = @" + private const string MicrosoftAspNetCoreHttpNamespaceCSharpSourceCode = @" namespace Microsoft.AspNetCore.Http { public interface IResponseCookies @@ -48,8 +47,19 @@ public void Append(string key, string value, CookieOptions options) } } }"; + protected void VerifyCSharpWithDependencies(string source, params DiagnosticResult[] expected) + { this.VerifyCSharp( - new[] { source, microsoftAspNetCoreHttpNamespaceCSharpSourceCode }.ToFileAndSource(), + new[] { source, MicrosoftAspNetCoreHttpNamespaceCSharpSourceCode }.ToFileAndSource(), + expected); + } + + protected void VerifyCSharpWithDependencies(string source, FileAndSource additionalFile, params DiagnosticResult[] expected) + { + this.VerifyCSharp( + new[] { source, MicrosoftAspNetCoreHttpNamespaceCSharpSourceCode }, + additionalFile, + ReferenceFlags.None, expected); } @@ -358,6 +368,39 @@ public void TestMethod(string key, string value) }"); } + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = TestMethod")] + [InlineData(@"dotnet_code_quality.CA5382.excluded_symbol_names = TestMethod + dotnet_code_quality.CA5383.excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = TestMethod")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(12, 9, UseSecureCookiesASPNetCore.DefinitelyUseSecureCookiesASPNetCoreRule) + }; + } + + VerifyCSharpWithDependencies(@" +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Internal; + +class TestClass +{ + public void TestMethod(string key, string value) + { + var cookieOptions = new CookieOptions(); + cookieOptions.Secure = false; + var responseCookies = new ResponseCookies(); + responseCookies.Append(key, value, cookieOptions); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { return new UseSecureCookiesASPNetCore(); diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseSharedAccessProtocolHttpsOnlyTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseSharedAccessProtocolHttpsOnlyTests.cs index c201511636..2cb8a1b663 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseSharedAccessProtocolHttpsOnlyTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Security/UseSharedAccessProtocolHttpsOnlyTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Test.Utilities; @@ -9,9 +10,7 @@ namespace Microsoft.NetCore.Analyzers.Security.UnitTests { public class UseSharedAccessProtocolHttpsOnlyTests : DiagnosticAnalyzerTestBase { - protected void VerifyCSharpWithDependencies(string source, params DiagnosticResult[] expected) - { - string microsoftWindowsAzureStorageCSharpSourceCode = @" + private const string MicrosoftWindowsAzureStorageCSharpSourceCode = @" using System; namespace Microsoft.WindowsAzure.Storage @@ -69,8 +68,20 @@ public sealed class SharedAccessFileHeaders } } }"; + + protected void VerifyCSharpWithDependencies(string source, params DiagnosticResult[] expected) + { this.VerifyCSharp( - new[] { source, microsoftWindowsAzureStorageCSharpSourceCode }.ToFileAndSource(), + new[] { source, MicrosoftWindowsAzureStorageCSharpSourceCode }.ToFileAndSource(), + expected); + } + + protected void VerifyCSharpWithDependencies(string source, FileAndSource additionalFile, params DiagnosticResult[] expected) + { + this.VerifyCSharp( + new[] { source, MicrosoftWindowsAzureStorageCSharpSourceCode }, + additionalFile, + ReferenceFlags.None, expected); } @@ -206,6 +217,38 @@ public void TestMethod() }"); } + [Theory] + [InlineData("")] + [InlineData("dotnet_code_quality.excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality." + UseSharedAccessProtocolHttpsOnly.DiagnosticId + ".excluded_symbol_names = TestMethod")] + [InlineData("dotnet_code_quality.dataflow.excluded_symbol_names = TestMethod")] + public void EditorConfigConfiguration_ExcludedSymbolNamesOption(string editorConfigText) + { + var expected = Array.Empty(); + if (editorConfigText.Length == 0) + { + expected = new DiagnosticResult[] + { + GetCSharpResultAt(12, 9, UseSharedAccessProtocolHttpsOnly.Rule) + }; + } + + VerifyCSharpWithDependencies(@" +using System; +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.File; + +class TestClass +{ + public void TestMethod(SharedAccessFilePolicy policy, SharedAccessFileHeaders headers, string groupPolicyIdentifier, IPAddressOrRange ipAddressOrRange) + { + var cloudFile = new CloudFile(); + var protocols = SharedAccessProtocol.HttpsOrHttp; + cloudFile.GetSharedAccessSignature(policy, headers, groupPolicyIdentifier, protocols, ipAddressOrRange); + } +}", GetEditorConfigAdditionalFile(editorConfigText), expected); + } + protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { return new UseSharedAccessProtocolHttpsOnly(); diff --git a/src/Test.Utilities/DiagnosticAnalyzerTestBase.cs b/src/Test.Utilities/DiagnosticAnalyzerTestBase.cs index 1cc84fe1f0..ca7c3f5d5d 100644 --- a/src/Test.Utilities/DiagnosticAnalyzerTestBase.cs +++ b/src/Test.Utilities/DiagnosticAnalyzerTestBase.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.IO; using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; @@ -177,22 +179,22 @@ private static (string path, LinePosition location)[] ParseResultLocations(strin protected void VerifyCSharpUnsafeCode(string source, params DiagnosticResult[] expected) { - Verify(new[] { source }.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, true, ReferenceFlags.None, compilationOptions: null, parseOptions: null, expected: expected); + Verify(new[] { source }.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, true, ReferenceFlags.None, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyCSharp(string source, params DiagnosticResult[] expected) { - Verify(new[] { source }.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, expected: expected); + Verify(new[] { source }.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyCSharp(string source, CompilationOptions compilationOptions = null, ParseOptions parseOptions = null, params DiagnosticResult[] expected) { - Verify(new[] { source }.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions, parseOptions, expected: expected); + Verify(new[] { source }.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions, parseOptions, additionalFiles: null, expected: expected); } protected void VerifyCSharp(string source, TestValidationMode validationMode, params DiagnosticResult[] expected) { - Verify(new[] { source }.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), validationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, expected: expected); + Verify(new[] { source }.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), validationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyCSharp(string source, ReferenceFlags referenceFlags, params DiagnosticResult[] expected) @@ -207,17 +209,23 @@ protected void VerifyCSharp(string source, ReferenceFlags referenceFlags, TestVa protected void VerifyCSharp(string[] sources, params DiagnosticResult[] expected) { - Verify(sources.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, expected: expected); + Verify(sources.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyCSharp(string[] sources, ReferenceFlags referenceFlags, params DiagnosticResult[] expected) { - Verify(sources.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, referenceFlags, compilationOptions: null, parseOptions: null, expected: expected); + Verify(sources.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, referenceFlags, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); + } + + protected void VerifyCSharp(string[] sources, FileAndSource additionalFile, ReferenceFlags referenceFlags, params DiagnosticResult[] expected) + { + var additionalFiles = new[] { GetAdditionalTextFile(additionalFile.FilePath, additionalFile.Source) }; + Verify(sources.ToFileAndSource(), LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, referenceFlags, compilationOptions: null, parseOptions: null, additionalFiles: additionalFiles, expected: expected); } protected void VerifyCSharp(FileAndSource[] sources, params DiagnosticResult[] expected) { - Verify(sources, LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, expected: expected); + Verify(sources, LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyCSharp(string source, FileAndSource additionalText, params DiagnosticResult[] expected) @@ -233,27 +241,32 @@ protected void VerifyCSharp(string source, FileAndSource additionalText, Compila protected void VerifyCSharpAcrossTwoAssemblies(string dependencySource, string source, params DiagnosticResult[] expected) { - VerifyAcrossTwoAssemblies(dependencySource, source, LanguageNames.CSharp, expected); + VerifyAcrossTwoAssemblies(dependencySource, source, LanguageNames.CSharp, additionalFileOpt: null, expected); + } + + protected void VerifyCSharpAcrossTwoAssemblies(string dependencySource, string source, FileAndSource additionalFile, params DiagnosticResult[] expected) + { + VerifyAcrossTwoAssemblies(dependencySource, source, LanguageNames.CSharp, additionalFile, expected); } protected void VerifyBasic(string source, params DiagnosticResult[] expected) { - Verify(new[] { source }.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, expected: expected); + Verify(new[] { source }.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyBasic(string source, CompilationOptions compilationOptions = null, ParseOptions parseOptions = null, params DiagnosticResult[] expected) { - Verify(new[] { source }.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions, parseOptions, expected: expected); + Verify(new[] { source }.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions, parseOptions, additionalFiles: null, expected: expected); } protected void VerifyBasic(string source, TestValidationMode validationMode, params DiagnosticResult[] expected) { - Verify(new[] { source }.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), validationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, expected: expected); + Verify(new[] { source }.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), validationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyBasic(string source, TestValidationMode validationMode, CompilationOptions compilationOptions = null, ParseOptions parseOptions = null, params DiagnosticResult[] expected) { - Verify(new[] { source }.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), validationMode, false, ReferenceFlags.None, compilationOptions, parseOptions, expected: expected); + Verify(new[] { source }.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), validationMode, false, ReferenceFlags.None, compilationOptions, parseOptions, additionalFiles: null, expected: expected); } protected void VerifyBasic(string source, ReferenceFlags referenceFlags, params DiagnosticResult[] expected) @@ -268,17 +281,17 @@ protected void VerifyBasic(string source, ReferenceFlags referenceFlags, TestVal protected void VerifyBasic(string[] sources, params DiagnosticResult[] expected) { - Verify(sources.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, expected: expected); + Verify(sources.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyBasic(string[] sources, ReferenceFlags referenceFlags, params DiagnosticResult[] expected) { - Verify(sources.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, referenceFlags, compilationOptions: null, parseOptions: null, expected: expected); + Verify(sources.ToFileAndSource(), LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, referenceFlags, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyBasic(FileAndSource[] sources, params DiagnosticResult[] expected) { - Verify(sources, LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, expected: expected); + Verify(sources, LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), DefaultTestValidationMode, false, ReferenceFlags.None, compilationOptions: null, parseOptions: null, additionalFiles: null, expected: expected); } protected void VerifyBasic(string source, FileAndSource additionalText, params DiagnosticResult[] expected) @@ -294,7 +307,12 @@ protected void VerifyBasic(string source, FileAndSource additionalText, Compilat protected void VerifyBasicAcrossTwoAssemblies(string dependencySource, string source, params DiagnosticResult[] expected) { - VerifyAcrossTwoAssemblies(dependencySource, source, LanguageNames.VisualBasic, expected); + VerifyAcrossTwoAssemblies(dependencySource, source, LanguageNames.VisualBasic, additionalFileOpt: null, expected); + } + + protected void VerifyBasicAcrossTwoAssemblies(string dependencySource, string source, FileAndSource additionalFile, params DiagnosticResult[] expected) + { + VerifyAcrossTwoAssemblies(dependencySource, source, LanguageNames.VisualBasic, additionalFile, expected); } protected void Verify(string source, string language, DiagnosticAnalyzer analyzer, IEnumerable additionalFiles, CompilationOptions compilationOptions, ParseOptions parseOptions, params DiagnosticResult[] expected) @@ -309,13 +327,13 @@ private void Verify(string source, string language, DiagnosticAnalyzer analyzer, diagnostics.Verify(analyzer, this.Output, ExpectedDiagnosticsAssertionTemplate, GetDefaultPath(language), expected); } - private void Verify(FileAndSource[] sources, string language, DiagnosticAnalyzer analyzer, TestValidationMode validationMode, bool allowUnsafeCode, ReferenceFlags referenceFlags, CompilationOptions compilationOptions, ParseOptions parseOptions, params DiagnosticResult[] expected) + private void Verify(FileAndSource[] sources, string language, DiagnosticAnalyzer analyzer, TestValidationMode validationMode, bool allowUnsafeCode, ReferenceFlags referenceFlags, CompilationOptions compilationOptions, ParseOptions parseOptions, IEnumerable additionalFiles, params DiagnosticResult[] expected) { - var diagnostics = GetSortedDiagnostics(sources, language, analyzer, compilationOptions, parseOptions, validationMode, referenceFlags: referenceFlags, allowUnsafeCode: allowUnsafeCode); + var diagnostics = GetSortedDiagnostics(sources, language, analyzer, compilationOptions, parseOptions, validationMode, referenceFlags: referenceFlags, allowUnsafeCode: allowUnsafeCode, additionalFiles: additionalFiles); diagnostics.Verify(analyzer, this.Output, ExpectedDiagnosticsAssertionTemplate, GetDefaultPath(language), expected); } - private void VerifyAcrossTwoAssemblies(string dependencySource, string source, string language, params DiagnosticResult[] expected) + private void VerifyAcrossTwoAssemblies(string dependencySource, string source, string language, FileAndSource? additionalFileOpt, params DiagnosticResult[] expected) { Debug.Assert(language == LanguageNames.CSharp || language == LanguageNames.VisualBasic); @@ -324,8 +342,16 @@ private void VerifyAcrossTwoAssemblies(string dependencySource, string source, s CreateProject(new[] { source }, language: language, referenceFlags: ReferenceFlags.RemoveCodeAnalysis, addToSolution: dependencyProject.Solution) .AddProjectReference(new ProjectReference(dependencyProject.Id)); + IEnumerable additionalFiles = null; + if (additionalFileOpt.HasValue) + { + var additionalFile = GetAdditionalTextFile(additionalFileOpt.Value.FilePath, additionalFileOpt.Value.Source); + additionalFiles = new[] { additionalFile }; + project = project.AddAdditionalDocument(additionalFileOpt.Value.FilePath, additionalFileOpt.Value.Source).Project; + } + var analyzer = language == LanguageNames.CSharp ? GetCSharpDiagnosticAnalyzer() : GetBasicDiagnosticAnalyzer(); - GetSortedDiagnostics(analyzer, project.Documents.ToArray()).Verify(analyzer, GetDefaultPath(language), expected); + GetSortedDiagnostics(analyzer, project.Documents.ToArray(), additionalFiles: additionalFiles).Verify(analyzer, GetDefaultPath(language), expected); } protected static string GetDefaultPath(string language) => diff --git a/src/Utilities.UnitTests/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisTests.cs b/src/Utilities.UnitTests/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisTests.cs index 38cf98a64d..6eb95e910a 100644 --- a/src/Utilities.UnitTests/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisTests.cs +++ b/src/Utilities.UnitTests/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisTests.cs @@ -79,6 +79,7 @@ private void VerifyCSharp( operation.GetEnclosingControlFlowGraph(), compilation, symbol, + new AnalyzerOptions(ImmutableArray.Empty), propertySetAnalysisParameters.TypeToTrack, propertySetAnalysisParameters.ConstructorMapper, propertySetAnalysisParameters.PropertyMapperCollection, diff --git a/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs b/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs index 1007a3ba78..40ffaec2e5 100644 --- a/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs +++ b/src/Utilities/Compiler/Options/CategorizedAnalyzerConfigOptions.cs @@ -120,6 +120,7 @@ private T ComputeOptionValue(string optionName, DiagnosticDescriptor rule, Tr { if (TryGetSpecificOptionValue(rule.Id, out var optionValue) || TryGetSpecificOptionValue(rule.Category, out optionValue) || + TryGetAnySpecificOptionValue(rule.CustomTags, out optionValue) || TryGetGeneralOptionValue(out optionValue)) { return optionValue; @@ -128,9 +129,7 @@ private T ComputeOptionValue(string optionName, DiagnosticDescriptor rule, Tr return defaultValue; // Local functions. -#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/32973 bool TryGetSpecificOptionValue(string specificOptionKey, out T specificOptionValue) -#pragma warning restore IDE0060 // Remove unused parameter { if (SpecificOptions.TryGetValue(specificOptionKey, out var specificRuleOptions) && specificRuleOptions.TryGetValue(optionName, out var valueString)) @@ -142,9 +141,21 @@ bool TryGetSpecificOptionValue(string specificOptionKey, out T specificOptionVal return false; } -#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/32973 + bool TryGetAnySpecificOptionValue(IEnumerable specificOptionKeys, out T specificOptionValue) + { + foreach (var specificOptionKey in specificOptionKeys) + { + if (TryGetSpecificOptionValue(specificOptionKey, out specificOptionValue)) + { + return true; + } + } + + specificOptionValue = defaultValue; + return false; + } + bool TryGetGeneralOptionValue(out T generalOptionValue) -#pragma warning restore IDE0060 // Remove unused parameter { if (GeneralOptions.TryGetValue(optionName, out var valueString)) { diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs index 1800982787..1434e43eef 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.CodeAnalysis.Diagnostics; #pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters @@ -21,6 +22,7 @@ private CopyAnalysis(CopyDataFlowOperationVisitor operationVisitor) public static CopyAnalysisResult TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, @@ -29,11 +31,11 @@ public static CopyAnalysisResult TryGetOrComputeResult( bool exceptionPathsAnalysis = false) { var pointsToAnalysisResultOpt = performPointsToAnalysis ? - PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, interproceduralAnalysisConfig, + PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt, pessimisticAnalysis, performCopyAnalysis: false, exceptionPathsAnalysis) : null; var analysisContext = CopyAnalysisContext.Create(CopyAbstractValueDomain.Default, wellKnownTypeProvider, - cfg, owningSymbol, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, pointsToAnalysisResultOpt, + cfg, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, pointsToAnalysisResultOpt, TryGetOrComputeResultForAnalysisContext, interproceduralAnalysisPredicateOpt); return TryGetOrComputeResultForAnalysisContext(analysisContext); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisContext.cs index 8f7bcc019c..202faa0a69 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysisContext.cs @@ -2,6 +2,7 @@ using System; using Analyzer.Utilities.PooledObjects; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.ValueContentAnalysis; @@ -23,6 +24,7 @@ private CopyAnalysisContext( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, bool exceptionPathsAnalysis, @@ -31,7 +33,7 @@ private CopyAnalysisContext( ControlFlowGraph parentControlFlowGraphOpt, InterproceduralCopyAnalysisData interproceduralAnalysisDataOpt, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) - : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, interproceduralAnalysisConfig, pessimisticAnalysis, + : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: true, exceptionPathsAnalysis, copyAnalysisResultOpt: null, pointsToAnalysisResultOpt, valueContentAnalysisResultOpt: null, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt, interproceduralAnalysisDataOpt, interproceduralAnalysisPredicateOpt) { @@ -42,6 +44,7 @@ internal static CopyAnalysisContext Create( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, bool exceptionPathsAnalysis, @@ -49,7 +52,7 @@ internal static CopyAnalysisContext Create( Func tryGetOrComputeAnalysisResult, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) { - return new CopyAnalysisContext(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, + return new CopyAnalysisContext(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, pointsToAnalysisResultOpt, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt: null, interproceduralAnalysisDataOpt: null, interproceduralAnalysisPredicateOpt); } @@ -63,7 +66,7 @@ public override CopyAnalysisContext ForkForInterproceduralAnalysis( ValueContentAnalysisResult valueContentAnalysisResultOpt, InterproceduralCopyAnalysisData interproceduralAnalysisData) { - return new CopyAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, InterproceduralAnalysisConfiguration, + return new CopyAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, AnalyzerOptions, InterproceduralAnalysisConfiguration, PessimisticAnalysis, ExceptionPathsAnalysis, pointsToAnalysisResultOpt, TryGetOrComputeAnalysisResult, ControlFlowGraph, interproceduralAnalysisData, InterproceduralAnalysisPredicateOpt); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs index b0f2766150..d3da820da8 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Threading; using Analyzer.Utilities; +using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; @@ -49,13 +50,15 @@ public static DisposeAnalysisResult TryGetOrComputeResult( bool defaultDisposeOwnershipTransferAtConstructor = false, bool defaultDisposeOwnershipTransferAtMethodCall = false) { + Debug.Assert(!owningSymbol.IsConfiguredToSkipAnalysis(analyzerOptions, rule, wellKnownTypeProvider.Compilation, cancellationToken)); + var interproceduralAnalysisConfig = InterproceduralAnalysisConfiguration.Create( analyzerOptions, rule, interproceduralAnalysisKind, cancellationToken); var disposeOwnershipTransferAtConstructor = analyzerOptions.GetDisposeOwnershipTransferAtConstructorOption( rule, defaultValue: defaultDisposeOwnershipTransferAtConstructor, cancellationToken); var disposeOwnershipTransferAtMethodCall = analyzerOptions.GetDisposeOwnershipTransferAtMethodCall( rule, defaultValue: defaultDisposeOwnershipTransferAtMethodCall, cancellationToken); - return TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, + return TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt, disposeOwnershipTransferLikelyTypes, disposeOwnershipTransferAtConstructor, disposeOwnershipTransferAtMethodCall, trackInstanceFields, exceptionPathsAnalysis, @@ -66,6 +69,7 @@ public static DisposeAnalysisResult TryGetOrComputeResult( private static DisposeAnalysisResult TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, @@ -82,7 +86,7 @@ private static DisposeAnalysisResult TryGetOrComputeResult( Debug.Assert(owningSymbol != null); pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult( - cfg, owningSymbol, wellKnownTypeProvider, interproceduralAnalysisConfig, + cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt, PessimisticAnalysis, performCopyAnalysis, exceptionPathsAnalysis); if (pointsToAnalysisResult == null) { @@ -90,7 +94,7 @@ private static DisposeAnalysisResult TryGetOrComputeResult( } var analysisContext = DisposeAnalysisContext.Create( - DisposeAbstractValueDomain.Default, wellKnownTypeProvider, cfg, owningSymbol, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt, + DisposeAbstractValueDomain.Default, wellKnownTypeProvider, cfg, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt, PessimisticAnalysis, exceptionPathsAnalysis, pointsToAnalysisResult, TryGetOrComputeResultForAnalysisContext, disposeOwnershipTransferLikelyTypes, disposeOwnershipTransferAtConstructor, disposeOwnershipTransferAtMethodCall, trackInstanceFields); return TryGetOrComputeResultForAnalysisContext(analysisContext); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisContext.cs index fc7c87ab4f..274805b56d 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysisContext.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using Analyzer.Utilities; using Analyzer.Utilities.PooledObjects; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.ValueContentAnalysis; @@ -28,6 +29,7 @@ private DisposeAnalysisContext( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, bool exceptionPathsAnalysis, @@ -41,7 +43,7 @@ private DisposeAnalysisContext( InterproceduralDisposeAnalysisData interproceduralAnalysisDataOpt, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, - owningSymbol, interproceduralAnalysisConfig, pessimisticAnalysis, + owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: false, exceptionPathsAnalysis, copyAnalysisResultOpt: null, @@ -63,6 +65,7 @@ internal static DisposeAnalysisContext Create( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, bool pessimisticAnalysis, @@ -76,7 +79,7 @@ internal static DisposeAnalysisContext Create( { return new DisposeAnalysisContext( valueDomain, wellKnownTypeProvider, controlFlowGraph, - owningSymbol, interproceduralAnalysisConfig, pessimisticAnalysis, + owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, pointsToAnalysisResultOpt, tryGetOrComputeAnalysisResult, disposeOwnershipTransferLikelyTypes, disposeOwnershipTransferAtConstructor, disposeOwnershipTransferAtMethodCall, trackInstanceFields, parentControlFlowGraphOpt: null, interproceduralAnalysisDataOpt: null, @@ -96,7 +99,7 @@ public override DisposeAnalysisContext ForkForInterproceduralAnalysis( Debug.Assert(copyAnalysisResultOpt == null); Debug.Assert(valueContentAnalysisResultOpt == null); - return new DisposeAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, InterproceduralAnalysisConfiguration, PessimisticAnalysis, + return new DisposeAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, AnalyzerOptions, InterproceduralAnalysisConfiguration, PessimisticAnalysis, ExceptionPathsAnalysis, pointsToAnalysisResultOpt, TryGetOrComputeAnalysisResult, DisposeOwnershipTransferLikelyTypes, DisposeOwnershipTransferAtConstructor, DisposeOwnershipTransferAtMethodCall, TrackInstanceFields, ControlFlowGraph, interproceduralAnalysisData, InterproceduralAnalysisPredicateOpt); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs index a1dca2738c..f0936c67cf 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysis.cs @@ -39,11 +39,13 @@ public static ImmutableDictionary GetOrComputeHaza uint defaultMaxInterproceduralMethodCallChain = 1, // By default, we only want to track method calls one level down. bool pessimisticAnalysis = true) { + Debug.Assert(!owningSymbol.IsConfiguredToSkipAnalysis(analyzerOptions, rule, compilation, cancellationToken)); + var interproceduralAnalysisConfig = InterproceduralAnalysisConfiguration.Create( analyzerOptions, rule, interproceduralAnalysisKind, cancellationToken, defaultMaxInterproceduralMethodCallChain); var performCopyAnalysis = analyzerOptions.GetCopyAnalysisOption(rule, defaultValue: false, cancellationToken); var nullCheckValidationMethods = analyzerOptions.GetNullCheckValidationMethodsOption(rule, compilation, cancellationToken); - return GetOrComputeHazardousParameterUsages(topmostBlock, compilation, owningSymbol, + return GetOrComputeHazardousParameterUsages(topmostBlock, compilation, owningSymbol, analyzerOptions, nullCheckValidationMethods, interproceduralAnalysisConfig, performCopyAnalysis, pessimisticAnalysis); } @@ -51,6 +53,7 @@ private static ImmutableDictionary GetOrComputeHaz IBlockOperation topmostBlock, Compilation compilation, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, SymbolNamesOption nullCheckValidationMethods, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool performCopyAnalysis, @@ -60,11 +63,11 @@ private static ImmutableDictionary GetOrComputeHaz var cfg = topmostBlock.GetEnclosingControlFlowGraph(); var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); - var pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, + var pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis, performCopyAnalysis); if (pointsToAnalysisResult != null) { - var result = TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, + var result = TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult); if (result != null) { @@ -78,6 +81,7 @@ private static ImmutableDictionary GetOrComputeHaz private static ParameterValidationAnalysisResult TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, SymbolNamesOption nullCheckValidationMethods, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, @@ -87,7 +91,7 @@ private static ParameterValidationAnalysisResult TryGetOrComputeResult( Debug.Assert(pointsToAnalysisResult != null); var analysisContext = ParameterValidationAnalysisContext.Create(ParameterValidationAbstractValueDomain.Default, - wellKnownTypeProvider, cfg, owningSymbol, nullCheckValidationMethods, interproceduralAnalysisConfig, + wellKnownTypeProvider, cfg, owningSymbol, analyzerOptions, nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult, TryGetOrComputeResultForAnalysisContext); return TryGetOrComputeResultForAnalysisContext(analysisContext); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysisContext.cs index bf067ba48d..c991c37bc7 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ParameterValidationAnalysis/ParameterValidationAnalysisContext.cs @@ -7,6 +7,7 @@ using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Analyzer.Utilities.PooledObjects; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.ValueContentAnalysis; @@ -30,6 +31,7 @@ private ParameterValidationAnalysisContext( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, SymbolNamesOption nullCheckValidationMethods, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, @@ -38,7 +40,7 @@ private ParameterValidationAnalysisContext( ControlFlowGraph parentControlFlowGraphOpt, InterproceduralParameterValidationAnalysisData interproceduralAnalysisDataOpt, bool trackHazardousParameterUsages) - : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, interproceduralAnalysisConfig, + : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: false, exceptionPathsAnalysis: false, copyAnalysisResultOpt: null, pointsToAnalysisResultOpt, valueContentAnalysisResultOpt: null, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt, interproceduralAnalysisDataOpt, @@ -53,6 +55,7 @@ public static ParameterValidationAnalysisContext Create( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, SymbolNamesOption nullCheckValidationMethods, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, @@ -61,7 +64,7 @@ public static ParameterValidationAnalysisContext Create( { return new ParameterValidationAnalysisContext( valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, - nullCheckValidationMethods, interproceduralAnalysisConfig, + analyzerOptions, nullCheckValidationMethods, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResultOpt, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt: null, interproceduralAnalysisDataOpt: null, trackHazardousParameterUsages: false); } @@ -82,7 +85,7 @@ public override ParameterValidationAnalysisContext ForkForInterproceduralAnalysi // Do not invoke any interprocedural analysis more than one level down. // We only care about analyzing validation methods. return new ParameterValidationAnalysisContext( - ValueDomain, WellKnownTypeProvider, invokedCfg, invokedMethod, + ValueDomain, WellKnownTypeProvider, invokedCfg, invokedMethod, AnalyzerOptions, NullCheckValidationMethodNames, InterproceduralAnalysisConfiguration, PessimisticAnalysis, pointsToAnalysisResultOpt, TryGetOrComputeAnalysisResult, ControlFlowGraph, interproceduralAnalysisData, TrackHazardousParameterUsages); @@ -91,7 +94,7 @@ public override ParameterValidationAnalysisContext ForkForInterproceduralAnalysi public ParameterValidationAnalysisContext WithTrackHazardousParameterUsages() => new ParameterValidationAnalysisContext( ValueDomain, WellKnownTypeProvider, ControlFlowGraph, - OwningSymbol, NullCheckValidationMethodNames, + OwningSymbol, AnalyzerOptions, NullCheckValidationMethodNames, InterproceduralAnalysisConfiguration, PessimisticAnalysis, PointsToAnalysisResultOpt, TryGetOrComputeAnalysisResult, ParentControlFlowGraphOpt, InterproceduralAnalysisDataOpt, trackHazardousParameterUsages: true); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs index 2da00bb18f..71955cbc77 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs @@ -28,6 +28,7 @@ private PointsToAnalysis(PointsToAnalysisDomain analysisDomain, PointsToDataFlow public static PointsToAnalysisResult TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt, @@ -35,7 +36,7 @@ public static PointsToAnalysisResult TryGetOrComputeResult( bool performCopyAnalysis = true, bool exceptionPathsAnalysis = false) { - return TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, + return TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, out var _, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt, pessimisticAnalysis, performCopyAnalysis, exceptionPathsAnalysis); } @@ -43,6 +44,7 @@ public static PointsToAnalysisResult TryGetOrComputeResult( public static PointsToAnalysisResult TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, out CopyAnalysisResult copyAnalysisResultOpt, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, @@ -52,11 +54,11 @@ public static PointsToAnalysisResult TryGetOrComputeResult( bool exceptionPathsAnalysis = false) { copyAnalysisResultOpt = performCopyAnalysis ? - CopyAnalysis.CopyAnalysis.TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, interproceduralAnalysisConfig, + CopyAnalysis.CopyAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt, pessimisticAnalysis, performPointsToAnalysis: true, exceptionPathsAnalysis) : null; var analysisContext = PointsToAnalysisContext.Create(PointsToAbstractValueDomain.Default, wellKnownTypeProvider, cfg, - owningSymbol, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, copyAnalysisResultOpt, + owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, copyAnalysisResultOpt, TryGetOrComputeResultForAnalysisContext, interproceduralAnalysisPredicateOpt); return TryGetOrComputeResultForAnalysisContext(analysisContext); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysisContext.cs index b8caaef89f..c3c887b010 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysisContext.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; using Analyzer.Utilities.PooledObjects; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.ValueContentAnalysis; @@ -24,6 +25,7 @@ private PointsToAnalysisContext( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, bool exceptionPathsAnalysis, @@ -32,7 +34,7 @@ private PointsToAnalysisContext( ControlFlowGraph parentControlFlowGraphOpt, InterproceduralPointsToAnalysisData interproceduralAnalysisDataOpt, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) - : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, interproceduralAnalysisConfig, pessimisticAnalysis, + : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: true, exceptionPathsAnalysis, copyAnalysisResultOpt, pointsToAnalysisResultOpt: null, valueContentAnalysisResultOpt: null, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt, interproceduralAnalysisDataOpt, interproceduralAnalysisPredicateOpt) { @@ -43,6 +45,7 @@ internal static PointsToAnalysisContext Create( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, bool exceptionPathsAnalysis, @@ -50,7 +53,7 @@ internal static PointsToAnalysisContext Create( Func tryGetOrComputeAnalysisResult, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) { - return new PointsToAnalysisContext(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, interproceduralAnalysisConfig, + return new PointsToAnalysisContext(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, exceptionPathsAnalysis, copyAnalysisResultOpt, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt: null, interproceduralAnalysisDataOpt: null, interproceduralAnalysisPredicateOpt); } @@ -67,7 +70,7 @@ public override PointsToAnalysisContext ForkForInterproceduralAnalysis( Debug.Assert(pointsToAnalysisResultOpt == null); Debug.Assert(valueContentAnalysisResultOpt == null); - return new PointsToAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, InterproceduralAnalysisConfiguration, + return new PointsToAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, AnalyzerOptions, InterproceduralAnalysisConfiguration, PessimisticAnalysis, ExceptionPathsAnalysis, copyAnalysisResultOpt, TryGetOrComputeAnalysisResult, ControlFlowGraph, interproceduralAnalysisData, InterproceduralAnalysisPredicateOpt); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.cs index 46af64406b..902aa53c6e 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.cs @@ -8,6 +8,7 @@ using Analyzer.Utilities.Extensions; using Analyzer.Utilities.PooledObjects; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; @@ -49,6 +50,7 @@ internal static PropertySetAnalysisResult GetOrComputeResult( ControlFlowGraph cfg, Compilation compilation, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, string typeToTrackMetadataName, ConstructorMapper constructorMapper, PropertyMapperCollection propertyMappers, @@ -82,6 +84,7 @@ internal static PropertySetAnalysisResult GetOrComputeResult( pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( cfg, owningSymbol, + analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, @@ -99,6 +102,7 @@ internal static PropertySetAnalysisResult GetOrComputeResult( valueContentAnalysisResultOpt = ValueContentAnalysis.TryGetOrComputeResult( cfg, owningSymbol, + analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, out var copyAnalysisResult, @@ -116,6 +120,7 @@ internal static PropertySetAnalysisResult GetOrComputeResult( wellKnownTypeProvider, cfg, owningSymbol, + analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult, @@ -145,6 +150,7 @@ internal static PropertySetAnalysisResult GetOrComputeResult( public static PooledDictionary<(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> BatchGetOrComputeHazardousUsages( Compilation compilation, IEnumerable<(IOperation Operation, ISymbol ContainingSymbol)> rootOperationsNeedingAnalysis, + AnalyzerOptions analyzerOptions, string typeToTrackMetadataName, ConstructorMapper constructorMapper, PropertyMapperCollection propertyMappers, @@ -198,6 +204,7 @@ PropertySetAnalysisResult InvokeDfaAndAccumulateResults(ControlFlowGraph cfg, IS cfg, compilation, owningSymbol, + analyzerOptions, typeToTrackMetadataName, constructorMapper, propertyMappers, diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisContext.cs index db5126d8f4..32c2d65285 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisContext.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using Analyzer.Utilities.PooledObjects; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis; @@ -30,6 +31,7 @@ private PropertySetAnalysisContext( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, PointsToAnalysisResult pointsToAnalysisResult, @@ -47,6 +49,7 @@ private PropertySetAnalysisContext( wellKnownTypeProvider, controlFlowGraph, owningSymbol, + analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: false, @@ -71,6 +74,7 @@ public static PropertySetAnalysisContext Create( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, PointsToAnalysisResult pointsToAnalysisResult, @@ -86,6 +90,7 @@ public static PropertySetAnalysisContext Create( wellKnownTypeProvider, controlFlowGraph, owningSymbol, + analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult, @@ -117,6 +122,7 @@ public override PropertySetAnalysisContext ForkForInterproceduralAnalysis( WellKnownTypeProvider, invokedCfg, invokedMethod, + AnalyzerOptions, InterproceduralAnalysisConfiguration, PessimisticAnalysis, pointsToAnalysisResultOpt, diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs index 9f468c9aac..617c52cd65 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs @@ -37,7 +37,7 @@ internal static TaintedDataAnalysisResult TryGetOrComputeResult( { var interproceduralAnalysisConfig = InterproceduralAnalysisConfiguration.Create( analyzerOptions, rule, InterproceduralAnalysisKind.ContextSensitive, cancellationToken); - return TryGetOrComputeResult(cfg, compilation, containingMethod, taintedSourceInfos, + return TryGetOrComputeResult(cfg, compilation, containingMethod, analyzerOptions, taintedSourceInfos, taintedSanitizerInfos, taintedSinkInfos, interproceduralAnalysisConfig); } @@ -45,6 +45,7 @@ private static TaintedDataAnalysisResult TryGetOrComputeResult( ControlFlowGraph cfg, Compilation compilation, ISymbol containingMethod, + AnalyzerOptions analyzerOptions, TaintedDataSymbolMap taintedSourceInfos, TaintedDataSymbolMap taintedSanitizerInfos, TaintedDataSymbolMap taintedSinkInfos, @@ -59,6 +60,7 @@ private static TaintedDataAnalysisResult TryGetOrComputeResult( valueContentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( cfg, containingMethod, + analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, out copyAnalysisResult, @@ -75,6 +77,7 @@ private static TaintedDataAnalysisResult TryGetOrComputeResult( pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( cfg, containingMethod, + analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, @@ -91,6 +94,7 @@ private static TaintedDataAnalysisResult TryGetOrComputeResult( wellKnownTypeProvider, cfg, containingMethod, + analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis: false, copyAnalysisResultOpt: copyAnalysisResult, diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysisContext.cs index f3b5542cf9..ffcaebf0fb 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysisContext.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using Analyzer.Utilities.PooledObjects; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis; @@ -25,6 +26,7 @@ private TaintedDataAnalysisContext( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, CopyAnalysisResult copyAnalysisResultOpt, @@ -41,6 +43,7 @@ private TaintedDataAnalysisContext( wellKnownTypeProvider, controlFlowGraph, owningSymbol, + analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: false, @@ -65,6 +68,7 @@ public static TaintedDataAnalysisContext Create( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, CopyAnalysisResult copyAnalysisResultOpt, @@ -82,6 +86,7 @@ public static TaintedDataAnalysisContext Create( wellKnownTypeProvider, controlFlowGraph, owningSymbol, + analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, copyAnalysisResultOpt, @@ -109,6 +114,7 @@ public override TaintedDataAnalysisContext ForkForInterproceduralAnalysis( this.WellKnownTypeProvider, invokedCfg, invokedMethod, + this.AnalyzerOptions, this.InterproceduralAnalysisConfiguration, this.PessimisticAnalysis, copyAnalysisResultOpt, diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs index dc0307b6a6..f0069735a8 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; using System.Threading; using Analyzer.Utilities; +using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; @@ -52,9 +54,11 @@ public static ValueContentAnalysisResult TryGetOrComputeResult( bool performCopyAnalysisIfNotUserConfigured = true, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt = null) { + Debug.Assert(!owningSymbol.IsConfiguredToSkipAnalysis(analyzerOptions, rule, wellKnownTypeProvider.Compilation, cancellationToken)); + var interproceduralAnalysisConfig = InterproceduralAnalysisConfiguration.Create( analyzerOptions, rule, interproceduralAnalysisKind, cancellationToken); - return TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, + return TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, out copyAnalysisResultOpt, out pointsToAnalysisResultOpt, pessimisticAnalysis, performPointsToAnalysis, performCopyAnalysis: analyzerOptions.GetCopyAnalysisOption(rule, defaultValue: performCopyAnalysisIfNotUserConfigured, cancellationToken), @@ -64,6 +68,7 @@ public static ValueContentAnalysisResult TryGetOrComputeResult( internal static ValueContentAnalysisResult TryGetOrComputeResult( ControlFlowGraph cfg, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, WellKnownTypeProvider wellKnownTypeProvider, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, out CopyAnalysisResult copyAnalysisResultOpt, @@ -75,11 +80,11 @@ internal static ValueContentAnalysisResult TryGetOrComputeResult( { copyAnalysisResultOpt = null; pointsToAnalysisResultOpt = performPointsToAnalysis ? - PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, out copyAnalysisResultOpt, + PointsToAnalysis.PointsToAnalysis.TryGetOrComputeResult(cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, out copyAnalysisResultOpt, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt, pessimisticAnalysis, performCopyAnalysis) : null; var analysisContext = ValueContentAnalysisContext.Create( - ValueContentAbstractValueDomain.Default, wellKnownTypeProvider, cfg, owningSymbol, + ValueContentAbstractValueDomain.Default, wellKnownTypeProvider, cfg, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, copyAnalysisResultOpt, pointsToAnalysisResultOpt, TryGetOrComputeResultForAnalysisContext, interproceduralAnalysisPredicateOpt); return TryGetOrComputeResultForAnalysisContext(analysisContext); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs index 2f7ea61525..c280c4236f 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; using Analyzer.Utilities.PooledObjects; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; @@ -24,6 +25,7 @@ private ValueContentAnalysisContext( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, CopyAnalysisResult copyAnalysisResultOpt, @@ -32,7 +34,7 @@ private ValueContentAnalysisContext( ControlFlowGraph parentControlFlowGraphOpt, InterproceduralValueContentAnalysisData interproceduralAnalysisDataOpt, InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) - : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, interproceduralAnalysisConfig, + : base(valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, predicateAnalysis: true, exceptionPathsAnalysis: false, copyAnalysisResultOpt, pointsToAnalysisResultOpt, valueContentAnalysisResultOpt: null, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt, interproceduralAnalysisDataOpt, interproceduralAnalysisPredicateOpt) @@ -44,6 +46,7 @@ internal static ValueContentAnalysisContext Create( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, CopyAnalysisResult copyAnalysisResultOpt, @@ -52,7 +55,7 @@ internal static ValueContentAnalysisContext Create( InterproceduralAnalysisPredicate interproceduralAnalysisPredicateOpt) { return new ValueContentAnalysisContext( - valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, + valueDomain, wellKnownTypeProvider, controlFlowGraph, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, copyAnalysisResultOpt, pointsToAnalysisResultOpt, tryGetOrComputeAnalysisResult, parentControlFlowGraphOpt: null, interproceduralAnalysisDataOpt: null, interproceduralAnalysisPredicateOpt); } @@ -68,7 +71,7 @@ public override ValueContentAnalysisContext ForkForInterproceduralAnalysis( { Debug.Assert(valueContentAnalysisResultOpt == null); - return new ValueContentAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, InterproceduralAnalysisConfiguration, + return new ValueContentAnalysisContext(ValueDomain, WellKnownTypeProvider, invokedControlFlowGraph, invokedMethod, AnalyzerOptions, InterproceduralAnalysisConfiguration, PessimisticAnalysis, copyAnalysisResultOpt, pointsToAnalysisResultOpt, TryGetOrComputeAnalysisResult, ControlFlowGraph, interproceduralAnalysisData, InterproceduralAnalysisPredicateOpt); } diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs index 07577315af..5f39fcb953 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs @@ -5,6 +5,7 @@ using System.Linq; using Analyzer.Utilities; using Analyzer.Utilities.PooledObjects; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.CopyAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.PointsToAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow.ValueContentAnalysis; @@ -27,6 +28,7 @@ protected AbstractDataFlowAnalysisContext( WellKnownTypeProvider wellKnownTypeProvider, ControlFlowGraph controlFlowGraph, ISymbol owningSymbol, + AnalyzerOptions analyzerOptions, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis, bool predicateAnalysis, @@ -54,6 +56,7 @@ protected AbstractDataFlowAnalysisContext( ControlFlowGraph = controlFlowGraph; ParentControlFlowGraphOpt = parentControlFlowGraphOpt; OwningSymbol = owningSymbol; + AnalyzerOptions = analyzerOptions; InterproceduralAnalysisConfiguration = interproceduralAnalysisConfig; PessimisticAnalysis = pessimisticAnalysis; PredicateAnalysis = predicateAnalysis; @@ -70,6 +73,7 @@ protected AbstractDataFlowAnalysisContext( public WellKnownTypeProvider WellKnownTypeProvider { get; } public ControlFlowGraph ControlFlowGraph { get; } public ISymbol OwningSymbol { get; } + public AnalyzerOptions AnalyzerOptions { get; } public InterproceduralAnalysisConfiguration InterproceduralAnalysisConfiguration { get; } public bool PessimisticAnalysis { get; } public bool PredicateAnalysis { get; } @@ -152,6 +156,7 @@ protected sealed override void ComputeHashCodeParts(ArrayBuilder builder) builder.Add(ValueDomain.GetHashCode()); builder.Add(OwningSymbol.GetHashCode()); builder.Add(ControlFlowGraph.OriginalOperation.GetHashCode()); + builder.Add(AnalyzerOptions.GetHashCode()); builder.Add(InterproceduralAnalysisConfiguration.GetHashCode()); builder.Add(PessimisticAnalysis.GetHashCode()); builder.Add(PredicateAnalysis.GetHashCode()); diff --git a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs index fcff1fd6c2..1d100aad3e 100644 --- a/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs +++ b/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; +using System.Threading; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Analyzer.Utilities.PooledObjects; @@ -25,6 +26,15 @@ public abstract class DataFlowOperationVisitor where TAnalysisResult : IDataFlowAnalysisResult { + private static readonly DiagnosticDescriptor s_dummyDataflowAnalysisDescriptor = new DiagnosticDescriptor( + id: "InterproceduralDataflow", + title: string.Empty, + messageFormat: string.Empty, + category: string.Empty, + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true, + customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry); + private readonly ImmutableHashSet _lValueFlowCaptures; private readonly ImmutableDictionary.Builder _valueCacheBuilder; private readonly ImmutableDictionary.Builder _predicateValueKindCacheBuilder; @@ -1924,7 +1934,8 @@ private TAbstractAnalysisValue PerformInterproceduralAnalysis( // Bail out if configured not to execute interprocedural analysis. var skipInterproceduralAnalysis = !isLambdaOrLocalFunction && InterproceduralAnalysisKind == InterproceduralAnalysisKind.None || - DataFlowAnalysisContext.InterproceduralAnalysisPredicateOpt?.SkipInterproceduralAnalysis(invokedMethod, isLambdaOrLocalFunction) == true; + DataFlowAnalysisContext.InterproceduralAnalysisPredicateOpt?.SkipInterproceduralAnalysis(invokedMethod, isLambdaOrLocalFunction) == true || + invokedMethod.IsConfiguredToSkipAnalysis(DataFlowAnalysisContext.AnalyzerOptions, s_dummyDataflowAnalysisDescriptor, WellKnownTypeProvider.Compilation, CancellationToken.None); // Also bail out for non-source methods and methods where we are not sure about the actual runtime target method. if (skipInterproceduralAnalysis || From c7c8759a83960077691543cd71d86d2a7398366d Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 25 Jul 2019 17:31:02 -0700 Subject: [PATCH 2/2] Update documentation files --- .../Microsoft.CodeAnalysis.FxCopAnalyzers.md | 3 +- ...icrosoft.CodeAnalysis.FxCopAnalyzers.sarif | 53 ++++++++++++++++++- .../Microsoft.NetCore.Analyzers.md | 1 + .../Microsoft.NetCore.Analyzers.sarif | 53 ++++++++++++++++++- 4 files changed, 105 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.FxCopAnalyzers/Microsoft.CodeAnalysis.FxCopAnalyzers.md b/src/Microsoft.CodeAnalysis.FxCopAnalyzers/Microsoft.CodeAnalysis.FxCopAnalyzers.md index 0b1a2c14cd..d302fca025 100644 --- a/src/Microsoft.CodeAnalysis.FxCopAnalyzers/Microsoft.CodeAnalysis.FxCopAnalyzers.md +++ b/src/Microsoft.CodeAnalysis.FxCopAnalyzers/Microsoft.CodeAnalysis.FxCopAnalyzers.md @@ -186,4 +186,5 @@ Sr. No. | Rule ID | Title | Category | Enabled | CodeFix | Description | 183 | CA5387 | Do Not Use Weak Key Derivation Function With Insufficient Iteration Count | Security | False | False | When deriving cryptographic keys from user-provided inputs such as password, use sufficient iteration count (at least 100k). | 184 | CA5388 | Ensure Sufficient Iteration Count When Using Weak Key Derivation Function | Security | False | False | When deriving cryptographic keys from user-provided inputs such as password, use sufficient iteration count (at least 100k). | 185 | CA5389 | Do Not Add Archive Item's Path To The Target File System Path | Security | True | False | When extracting files from an archive and using the archive item's path, check if the path is safe. Archive path can be relative and can lead to file system access outside of the expected file system target path, leading to malicious config changes and remote code execution via lay-and-wait technique. | -186 | CA9999 | Analyzer version mismatch | Reliability | True | False | Analyzers in this package require a certain minimum version of Microsoft.CodeAnalysis to execute correctly. Refer to https://docs.microsoft.com/visualstudio/code-quality/install-fxcop-analyzers#fxcopanalyzers-package-versions to install the correct analyzer version. | +186 | CA5390 | Do Not Hard Code Encryption Key | Security | True | False | SymmetricAlgorithm's .Key property, or a method's rgbKey parameter, should never be a hardcoded value. | +187 | CA9999 | Analyzer version mismatch | Reliability | True | False | Analyzers in this package require a certain minimum version of Microsoft.CodeAnalysis to execute correctly. Refer to https://docs.microsoft.com/visualstudio/code-quality/install-fxcop-analyzers#fxcopanalyzers-package-versions to install the correct analyzer version. | diff --git a/src/Microsoft.CodeAnalysis.FxCopAnalyzers/Microsoft.CodeAnalysis.FxCopAnalyzers.sarif b/src/Microsoft.CodeAnalysis.FxCopAnalyzers/Microsoft.CodeAnalysis.FxCopAnalyzers.sarif index c37004ffe3..9b1d21db17 100644 --- a/src/Microsoft.CodeAnalysis.FxCopAnalyzers/Microsoft.CodeAnalysis.FxCopAnalyzers.sarif +++ b/src/Microsoft.CodeAnalysis.FxCopAnalyzers/Microsoft.CodeAnalysis.FxCopAnalyzers.sarif @@ -2471,6 +2471,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -2487,6 +2491,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -2535,6 +2543,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -2551,6 +2563,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -2583,6 +2599,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -2599,6 +2619,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -2629,6 +2653,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -2644,6 +2672,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -3388,7 +3420,6 @@ "Visual Basic" ], "tags": [ - "Dataflow", "Telemetry" ] } @@ -3407,7 +3438,6 @@ "Visual Basic" ], "tags": [ - "Dataflow", "Telemetry" ] } @@ -3487,6 +3517,25 @@ "Telemetry" ] } + }, + "CA5390": { + "id": "CA5390", + "shortDescription": "Do Not Hard Code Encryption Key", + "fullDescription": "SymmetricAlgorithm's .Key property, or a method's rgbKey parameter, should never be a hardcoded value.", + "defaultLevel": "warning", + "properties": { + "category": "Security", + "isEnabledByDefault": true, + "typeName": "DoNotHardCodeEncryptionKey", + "languages": [ + "C#", + "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" + ] + } } } }, diff --git a/src/Microsoft.NetCore.Analyzers/Microsoft.NetCore.Analyzers.md b/src/Microsoft.NetCore.Analyzers/Microsoft.NetCore.Analyzers.md index 5aa5a68096..24e1c942aa 100644 --- a/src/Microsoft.NetCore.Analyzers/Microsoft.NetCore.Analyzers.md +++ b/src/Microsoft.NetCore.Analyzers/Microsoft.NetCore.Analyzers.md @@ -93,3 +93,4 @@ Sr. No. | Rule ID | Title | Category | Enabled | CodeFix | Description | 90 | CA5387 | Do Not Use Weak Key Derivation Function With Insufficient Iteration Count | Security | False | False | When deriving cryptographic keys from user-provided inputs such as password, use sufficient iteration count (at least 100k). | 91 | CA5388 | Ensure Sufficient Iteration Count When Using Weak Key Derivation Function | Security | False | False | When deriving cryptographic keys from user-provided inputs such as password, use sufficient iteration count (at least 100k). | 92 | CA5389 | Do Not Add Archive Item's Path To The Target File System Path | Security | True | False | When extracting files from an archive and using the archive item's path, check if the path is safe. Archive path can be relative and can lead to file system access outside of the expected file system target path, leading to malicious config changes and remote code execution via lay-and-wait technique. | +93 | CA5390 | Do Not Hard Code Encryption Key | Security | True | False | SymmetricAlgorithm's .Key property, or a method's rgbKey parameter, should never be a hardcoded value. | diff --git a/src/Microsoft.NetCore.Analyzers/Microsoft.NetCore.Analyzers.sarif b/src/Microsoft.NetCore.Analyzers/Microsoft.NetCore.Analyzers.sarif index b8558b998c..2c5c2ab893 100644 --- a/src/Microsoft.NetCore.Analyzers/Microsoft.NetCore.Analyzers.sarif +++ b/src/Microsoft.NetCore.Analyzers/Microsoft.NetCore.Analyzers.sarif @@ -536,6 +536,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -552,6 +556,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -600,6 +608,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -616,6 +628,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -648,6 +664,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -664,6 +684,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -694,6 +718,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -709,6 +737,10 @@ "languages": [ "C#", "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" ] } }, @@ -1453,7 +1485,6 @@ "Visual Basic" ], "tags": [ - "Dataflow", "Telemetry" ] } @@ -1472,7 +1503,6 @@ "Visual Basic" ], "tags": [ - "Dataflow", "Telemetry" ] } @@ -1552,6 +1582,25 @@ "Telemetry" ] } + }, + "CA5390": { + "id": "CA5390", + "shortDescription": "Do Not Hard Code Encryption Key", + "fullDescription": "SymmetricAlgorithm's .Key property, or a method's rgbKey parameter, should never be a hardcoded value.", + "defaultLevel": "warning", + "properties": { + "category": "Security", + "isEnabledByDefault": true, + "typeName": "DoNotHardCodeEncryptionKey", + "languages": [ + "C#", + "Visual Basic" + ], + "tags": [ + "Dataflow", + "Telemetry" + ] + } } } },