Skip to content

Commit

Permalink
Fix S6964 FP: Properties decorated with the [BindNever] attribute (#9361
Browse files Browse the repository at this point in the history
)
  • Loading branch information
zsolt-kolbay-sonarsource authored May 30, 2024
1 parent bd737fd commit 80811f9
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 10 deletions.
22 changes: 16 additions & 6 deletions analyzers/rspec/cs/S6964.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,24 @@ <h2>Why is this an issue?</h2>
}
</pre>
<h3>Exceptions</h3>
<p>This rule does not raise an issue when:</p>
<p>This rule does not raise an issue when properties are decorated with the following attributes:</p>
<ul>
<li> properties are decorated with the <a
href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.validation.validateneverattribute">ValidateNever</a>
attribute. </li>
<li> properties are in model classes which are not in the same project as the Controller class that references them. This is due to a limitation of
Roslyn (see <a href="https://github.com/SonarSource/sonar-dotnet/issues/9243">here</a>). </li>
<li> <a
href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.validation.validateneverattribute">ValidateNever</a> </li>
<li> <a href="https://www.newtonsoft.com/json/help/html/JsonPropertyRequired.htm">JsonProperty(Required = Required.Always)</a> </li>
<li> <a href="https://www.newtonsoft.com/json/help/html/JsonPropertyRequired.htm">JsonProperty(Required = Required.AllowNull)</a> </li>
<li> <a href="https://www.newtonsoft.com/json/help/html/PropertyJsonIgnore.htm">Newtonsoft.Json.JsonIgnore</a> </li>
<li> <a href="https://www.newtonsoft.com/json/help/html/t_newtonsoft_json_jsonrequiredattribute.htm">Newtonsoft.Json.JsonRequired</a> </li>
<li> <a
href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonrequiredattribute">System.Text.Json.Serialization.JsonRequired</a> </li>
<li> <a
href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonignoreattribute">System.Text.Json.Serialization.JsonIgnore</a>
</li>
<li> <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.rangeattribute">Range</a> </li>
<li> <a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.bindneverattribute">BindNever</a> </li>
</ul>
<p>Additionally, this rule does not raise for properties in model classes that are not in the same project as the Controller class that references
them. This is due to a limitation of Roslyn (see <a href="https://github.com/SonarSource/sonar-dotnet/issues/9243">here</a>).</p>
<h2>How to fix it</h2>
<p>You should mark any model value-type property as <a
href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types">nullable</a>, <a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ public sealed class AvoidUnderPosting : SonarDiagnosticAnalyzer
KnownType.Microsoft_AspNetCore_Http_IFormFile,
KnownType.Microsoft_AspNetCore_Http_IFormFileCollection);
private static readonly ImmutableArray<KnownType> IgnoredAttributes = ImmutableArray.Create(
KnownType.System_Text_Json_Serialization_JsonIgnoreAttribute,
KnownType.System_Text_Json_Serialization_JsonRequiredAttribute,
KnownType.Microsoft_AspNetCore_Mvc_ModelBinding_BindNeverAttribute,
KnownType.Newtonsoft_Json_JsonIgnoreAttribute,
KnownType.Newtonsoft_Json_JsonRequiredAttribute,
KnownType.System_ComponentModel_DataAnnotations_RangeAttribute);
KnownType.System_ComponentModel_DataAnnotations_RangeAttribute,
KnownType.System_Text_Json_Serialization_JsonIgnoreAttribute,
KnownType.System_Text_Json_Serialization_JsonRequiredAttribute);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);

Expand Down Expand Up @@ -157,7 +158,8 @@ private static IEnumerable<INamedTypeSymbol> RelatedTypesToExamine(ITypeSymbol t
IArrayTypeSymbol array => RelatedTypesToExamine(array.ElementType, controllerType),
INamedTypeSymbol collection when collection.DerivesOrImplements(KnownType.System_Collections_Generic_IEnumerable_T) =>
collection.TypeArguments.SelectMany(x => RelatedTypesToExamine(x, controllerType)),
INamedTypeSymbol namedType when type.IsInSameAssembly(controllerType) => [namedType],
INamedTypeSymbol namedType when type.IsInSameAssembly(controllerType) && !type.HasAttribute(KnownType.Microsoft_AspNetCore_Mvc_ModelBinding_BindNeverAttribute) =>
[namedType],
_ => []
};

Expand Down
1 change: 1 addition & 0 deletions analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public sealed partial class KnownType
public static readonly KnownType Microsoft_AspNetCore_Mvc_IActionResult = new("Microsoft.AspNetCore.Mvc.IActionResult");
public static readonly KnownType Microsoft_AspNetCore_Mvc_IgnoreAntiforgeryTokenAttribute = new("Microsoft.AspNetCore.Mvc.IgnoreAntiforgeryTokenAttribute");
public static readonly KnownType Microsoft_AspNetCore_Mvc_Infrastructure_ActionResultObjectValueAttribute = new("Microsoft.AspNetCore.Mvc.Infrastructure.ActionResultObjectValueAttribute");
public static readonly KnownType Microsoft_AspNetCore_Mvc_ModelBinding_BindNeverAttribute = new("Microsoft.AspNetCore.Mvc.ModelBinding.BindNeverAttribute");
public static readonly KnownType Microsoft_AspNetCore_Mvc_ModelBinding_ModelStateDictionary = new("Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary");
public static readonly KnownType Microsoft_AspNetCore_Mvc_ModelBinding_Validation_ValidateNeverAttribute = new("Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidateNeverAttribute");
public static readonly KnownType Microsoft_AspNetCore_Mvc_NonActionAttribute = new("Microsoft.AspNetCore.Mvc.NonActionAttribute");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
Expand Down Expand Up @@ -314,3 +315,23 @@ public bool IsProperty // Noncompliant
set;
}
}

namespace UsingBindNeverAttribute
{
public class ModelWithBindNeverProperty
{
[BindNever] public int ValueProperty { get; set; }
}

[BindNever]
public class EntireModelWithBindNeverAttribute
{
public int ValueProperty { get; set; }
}

public class CustomController : Controller
{
[HttpGet] public IActionResult Get(ModelWithBindNeverProperty model) => View(model);
[HttpPost] public IActionResult Post(EntireModelWithBindNeverAttribute model) => View(model);
}
}

0 comments on commit 80811f9

Please sign in to comment.