From 80811f9a76a65c92e4c32cb434094f52db79ed5b Mon Sep 17 00:00:00 2001
From: Zsolt Kolbay
<121798625+zsolt-kolbay-sonarsource@users.noreply.github.com>
Date: Thu, 30 May 2024 15:57:03 +0200
Subject: [PATCH] Fix S6964 FP: Properties decorated with the [BindNever]
attribute (#9361)
---
analyzers/rspec/cs/S6964.html | 22 ++++++++++++++-----
.../Rules/AspNet/AvoidUnderPosting.cs | 10 +++++----
.../SonarAnalyzer.Common/Helpers/KnownType.cs | 1 +
.../TestCases/AspNet/AvoidUnderPosting.cs | 21 ++++++++++++++++++
4 files changed, 44 insertions(+), 10 deletions(-)
diff --git a/analyzers/rspec/cs/S6964.html b/analyzers/rspec/cs/S6964.html
index 026d6cbcdc2..503fb1e0722 100644
--- a/analyzers/rspec/cs/S6964.html
+++ b/analyzers/rspec/cs/S6964.html
@@ -20,14 +20,24 @@
Why is this an issue?
}
Exceptions
-This rule does not raise an issue when:
+This rule does not raise an issue when properties are decorated with the following attributes:
+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 here).
How to fix it
You should mark any model value-type property as nullable, 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 SupportedDiagnostics => ImmutableArray.Create(Rule);
@@ -157,7 +158,8 @@ private static IEnumerable 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],
_ => []
};
diff --git a/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs b/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs
index 4c0d9187b3c..e7e27702090 100644
--- a/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs
+++ b/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs
@@ -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");
diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/AspNet/AvoidUnderPosting.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/AspNet/AvoidUnderPosting.cs
index f7bdf1236b5..5ebf70d2fd9 100644
--- a/analyzers/tests/SonarAnalyzer.Test/TestCases/AspNet/AvoidUnderPosting.cs
+++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/AspNet/AvoidUnderPosting.cs
@@ -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;
@@ -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);
+ }
+}