Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analyzer for misusage of MaxResponseHeadersLength #6796

Merged
merged 20 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ Rule ID | Category | Severity | Notes
--------|----------|----------|-------
CA1514 | Maintainability | Info | AvoidLengthCheckWhenSlicingToEndAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514)
CA1515 | Maintainability | Disabled | MakeTypesInternal, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515)
CA2262 | Usage | Info | ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectly, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2262)
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,15 @@
<data name="ProvideCorrectArgumentToEnumHasFlagDescription" xml:space="preserve">
<value>'Enum.HasFlag' method expects the 'enum' argument to be of the same 'enum' type as the instance on which the method is invoked and that this 'enum' is marked with 'System.FlagsAttribute'. If these are different 'enum' types, an unhandled exception will be thrown at runtime. If the 'enum' type is not marked with 'System.FlagsAttribute' the call will always return 'false' at runtime.</value>
</data>
<data name="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyTitle" xml:space="preserve">
<value>Set 'MaxResponseHeadersLength' properly</value>
</data>
<data name="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyMessage" xml:space="preserve">
<value>Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</value>
</data>
<data name="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyDescription" xml:space="preserve">
<value>The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</value>
</data>
<data name="ProvideCorrectArgumentToEnumHasFlagMessageDifferentType" xml:space="preserve">
<value>The argument type, '{0}', must be the same as the enum type '{1}'</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.

using System.Collections.Immutable;
using System.Linq;
using Analyzer.Utilities;
using Analyzer.Utilities.Extensions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

namespace Microsoft.NetCore.Analyzers.Usage
{
using static MicrosoftNetCoreAnalyzersResources;

/// <summary>
/// CA2262: <inheritdoc cref="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyTitle"/>
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public sealed class ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectly : DiagnosticAnalyzer
{
private const string MaxResponseHeadersLengthPropertyName = "MaxResponseHeadersLength";
private const int MaxLimitToReport = 128;
internal const string RuleId = "CA2262";

internal static readonly DiagnosticDescriptor EnsureMaxResponseHeaderLengthRule = DiagnosticDescriptorHelper.Create(
RuleId,
CreateLocalizableResourceString(nameof(ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyTitle)),
CreateLocalizableResourceString(nameof(ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyMessage)),
DiagnosticCategory.Usage,
RuleLevel.IdeSuggestion,
description: CreateLocalizableResourceString(nameof(ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyDescription)),
isPortedFxCopRule: false,
isDataflowRule: false);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(EnsureMaxResponseHeaderLengthRule);

public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

context.RegisterCompilationStartAction(context =>
{
var httpClientHandlerPropSymbol = context.Compilation
.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNetHttpHttpClientHandler)
?.GetMembers(MaxResponseHeadersLengthPropertyName)
.FirstOrDefault();

var socketClientHandlerPropSymbol = context.Compilation
.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemNetHttpSocketsHttpHandler)
?.GetMembers(MaxResponseHeadersLengthPropertyName)
.FirstOrDefault();

if (httpClientHandlerPropSymbol is null || socketClientHandlerPropSymbol is null)
{
return;
}

ImmutableArray<ISymbol> symbols = ImmutableArray.Create(httpClientHandlerPropSymbol, socketClientHandlerPropSymbol);
context.RegisterOperationAction(context => AnalyzeSimpleAssignmentOperationAndCreateDiagnostic(context, symbols), OperationKind.SimpleAssignment);
});
}

private static void AnalyzeSimpleAssignmentOperationAndCreateDiagnostic(OperationAnalysisContext context, ImmutableArray<ISymbol> propSymbols)
{
var assignmentOperation = (ISimpleAssignmentOperation)context.Operation;

if (!IsValidPropertyAssignmentOperation(assignmentOperation, propSymbols))
{
return;
}

if (assignmentOperation.Value is null || !assignmentOperation.Value.ConstantValue.HasValue || assignmentOperation.Value.ConstantValue.Value is not int propertyValue)
{
return;
}

// If the user set the value to int.MaxValue, their intention is to disable the limit, and we shouldn't emit a warning.
if (propertyValue is > MaxLimitToReport and not int.MaxValue)
{
context.ReportDiagnostic(context.Operation.CreateDiagnostic(EnsureMaxResponseHeaderLengthRule, propertyValue));
}
}

private static bool IsValidPropertyAssignmentOperation(ISimpleAssignmentOperation operation, ImmutableArray<ISymbol> propSymbols)
{
if (operation.Target is not IPropertyReferenceOperation propertyReferenceOperation)
{
return false;
}

if (!propSymbols.Contains(propertyReferenceOperation.Member))
{
return false;
}

return operation.Value is IFieldReferenceOperation or ILiteralOperation or IBinaryOperation;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,21 @@ Obecné přetypování (IL unbox.any) používané sekvencí vrácenou metodou E
<target state="translated">Poskytněte metodám formátování správné argumenty</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyDescription">
<source>The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</source>
<target state="new">The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyMessage">
<source>Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</source>
<target state="new">Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyTitle">
<source>Set 'MaxResponseHeadersLength' properly</source>
<target state="new">Set 'MaxResponseHeadersLength' properly</target>
<note />
</trans-unit>
<trans-unit id="ProvidePublicParameterlessSafeHandleConstructorDescription">
<source>Providing a parameterless constructor that is as visible as the containing type for a type derived from 'System.Runtime.InteropServices.SafeHandle' enables better performance and usage with source-generated interop solutions.</source>
<target state="translated">Poskytnutí konstruktoru bez parametrů, který je viditelný jako nadřazený typ pro typ odvozený od System.Runtime.InteropServices.SafeHandle, umožňuje lepší výkon a využití s řešeními spolupráce generovanými zdroji.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,21 @@ Erweiterungen und benutzerdefinierte Konvertierungen werden bei generischen Type
<target state="translated">Geeignete Argumente für Formatierungsmethoden angeben</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyDescription">
<source>The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</source>
<target state="new">The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyMessage">
<source>Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</source>
<target state="new">Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyTitle">
<source>Set 'MaxResponseHeadersLength' properly</source>
<target state="new">Set 'MaxResponseHeadersLength' properly</target>
<note />
</trans-unit>
<trans-unit id="ProvidePublicParameterlessSafeHandleConstructorDescription">
<source>Providing a parameterless constructor that is as visible as the containing type for a type derived from 'System.Runtime.InteropServices.SafeHandle' enables better performance and usage with source-generated interop solutions.</source>
<target state="translated">Indem Sie für einen von "System.Runtime.InteropServices.SafeHandle" abgeleiteten Typ einen parameterlosen Konstruktor bereitstellen, der ebenso sichtbar ist wie der enthaltende Typ, erzielen Sie eine bessere Leistung und Nutzung mit aus der Quelle generierten Interop-Lösungen.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,21 @@ La ampliación y las conversiones definidas por el usuario no se admiten con tip
<target state="translated">Proporcionar argumentos correctos para los métodos de formato</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyDescription">
<source>The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</source>
<target state="new">The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyMessage">
<source>Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</source>
<target state="new">Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyTitle">
<source>Set 'MaxResponseHeadersLength' properly</source>
<target state="new">Set 'MaxResponseHeadersLength' properly</target>
<note />
</trans-unit>
<trans-unit id="ProvidePublicParameterlessSafeHandleConstructorDescription">
<source>Providing a parameterless constructor that is as visible as the containing type for a type derived from 'System.Runtime.InteropServices.SafeHandle' enables better performance and usage with source-generated interop solutions.</source>
<target state="translated">Proporcionar un constructor sin parámetros tan visible como el tipo contenedor para un tipo derivado de 'System.Runtime.InteropServices.SafeHandle' permite un mejor rendimiento y uso con soluciones de interoperabilidad generadas por el origen.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,21 @@ Les conversions étendues et définies par l’utilisateur ne sont pas prises en
<target state="translated">Indiquer le nombre correct d'arguments dans les méthodes de mise en forme</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyDescription">
<source>The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</source>
<target state="new">The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyMessage">
<source>Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</source>
<target state="new">Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyTitle">
<source>Set 'MaxResponseHeadersLength' properly</source>
<target state="new">Set 'MaxResponseHeadersLength' properly</target>
<note />
</trans-unit>
<trans-unit id="ProvidePublicParameterlessSafeHandleConstructorDescription">
<source>Providing a parameterless constructor that is as visible as the containing type for a type derived from 'System.Runtime.InteropServices.SafeHandle' enables better performance and usage with source-generated interop solutions.</source>
<target state="translated">La fourniture d’un constructeur sans paramètre qui est aussi visible que le type conteneur pour un type dérivé de ’System. Runtime. InteropServices. SafeHandle’ permet d’améliorer les performances et l’utilisation des solutions d’interopérabilité générées par le code source.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,21 @@ L'ampliamento e le conversioni definite dall'utente non sono supportate con tipi
<target state="translated">Fornire gli argomenti corretti ai metodi di formattazione</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyDescription">
<source>The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</source>
<target state="new">The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyMessage">
<source>Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</source>
<target state="new">Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyTitle">
<source>Set 'MaxResponseHeadersLength' properly</source>
<target state="new">Set 'MaxResponseHeadersLength' properly</target>
<note />
</trans-unit>
<trans-unit id="ProvidePublicParameterlessSafeHandleConstructorDescription">
<source>Providing a parameterless constructor that is as visible as the containing type for a type derived from 'System.Runtime.InteropServices.SafeHandle' enables better performance and usage with source-generated interop solutions.</source>
<target state="translated">La specifica di un costruttore senza parametri visibile come tipo che lo contiene per un tipo derivato da 'System.Runtime.InteropServices.SafeHandle' offre prestazioni migliori e ne consente l'utilizzo in soluzioni di interoperabilità generate da origini.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,21 @@ Enumerable.OfType&lt;T&gt; で使用されるジェネリック型チェック (
<target state="translated">書式設定メソッドに正しい引数を指定します</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyDescription">
<source>The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</source>
<target state="new">The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. That mean the provided value will be multiplied by 1024, the result might be too high than your intended value.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyMessage">
<source>Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</source>
<target state="new">Make sure the value '{0}' is provided correctly. This value is measured in kilobytes not bytes.</target>
<note />
</trans-unit>
<trans-unit id="ProvideHttpClientHandlerMaxResponseHeaderLengthValueCorrectlyTitle">
<source>Set 'MaxResponseHeadersLength' properly</source>
<target state="new">Set 'MaxResponseHeadersLength' properly</target>
<note />
</trans-unit>
<trans-unit id="ProvidePublicParameterlessSafeHandleConstructorDescription">
<source>Providing a parameterless constructor that is as visible as the containing type for a type derived from 'System.Runtime.InteropServices.SafeHandle' enables better performance and usage with source-generated interop solutions.</source>
<target state="translated">'System.Runtime.InteropServices.SafeHandle' から派生した型の包含型と同じように見えるパラメーターなしのコンストラクターを指定すると、ソース生成相互運用ソリューションのパフォーマンスと使用方法が向上します。</target>
Expand Down
Loading