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

Fix S2259 FP: PropertyReference does not learn from underlying symbol #9030

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,23 @@ protected override IPropertyReferenceOperationWrapper Convert(IOperation operati

protected override ProgramState PreProcess(ProgramState state, IPropertyReferenceOperationWrapper operation, bool isInLoop)
{
var symbol = operation.Instance.TrackedSymbol(state);
if (symbol is not null)
if (operation.WrappedOperation.TrackedSymbol(state) is { } propertySymbol && state[propertySymbol] is { } propertyValue)
{
state = state.SetOperationValue(operation, propertyValue);
}
var instanceSymbol = operation.Instance.TrackedSymbol(state);
if (instanceSymbol is not null)
{
if (!IsNullableProperty(operation, "HasValue"))
{
state = state.SetSymbolConstraint(symbol, ObjectConstraint.NotNull);
state = state.SetSymbolConstraint(instanceSymbol, ObjectConstraint.NotNull);
}
if (IsNullableProperty(operation, "Value") && state[symbol] is { } value)
if (IsNullableProperty(operation, "Value") && state[instanceSymbol] is { } instanceValue)
{
state = state.SetOperationValue(operation, value);
state = state.SetOperationValue(operation, instanceValue);
}
}
state = CollectionTracker.LearnFrom(state, operation, symbol);
return state;
return CollectionTracker.LearnFrom(state, operation, instanceSymbol);
}

protected override SymbolicConstraint BoolConstraintFromOperation(ProgramState state, IPropertyReferenceOperationWrapper operation) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using System.Data;
using Microsoft.CodeAnalysis.Operations;
using SonarAnalyzer.SymbolicExecution;
using SonarAnalyzer.SymbolicExecution.Constraints;
Expand Down Expand Up @@ -1066,16 +1065,22 @@ public void PropertyReference_Write_SetsNotNull()
[TestMethod]
public void PropertyReference_AutoProperty_IsTracked()
{
const string code = """
AutoProperty = null;
Tag("AfterSetNull", AutoProperty);
AutoProperty.ToString();
Tag("AfterReadReference", AutoProperty);
""";
var code = """
AutoProperty = null;
var x = AutoProperty;
Tag("AfterSetNull", AutoProperty);
Tag("AfterSetNull_Operation", x);
AutoProperty.ToString();
x = AutoProperty;
Tag("AfterReadReference", AutoProperty);
Tag("AfterReadReference_Operation", x);
""";
var validator = SETestContext.CreateCS(code).Validator;
validator.ValidateContainsOperation(OperationKind.PropertyReference);
validator.TagValue("AfterSetNull").Should().HaveOnlyConstraints(ObjectConstraint.Null);
validator.TagValue("AfterSetNull_Operation").Should().HaveOnlyConstraints(ObjectConstraint.Null);
validator.TagValue("AfterReadReference").Should().HaveOnlyConstraints(ObjectConstraint.NotNull);
validator.TagValue("AfterReadReference_Operation").Should().HaveOnlyConstraints(ObjectConstraint.NotNull);
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public void M()
Property = null;
_ = Property.HasValue; // Compliant
Property = null;
Property.GetType(); // FN https://github.com/SonarSource/sonar-dotnet/issues/6930
Property.GetType(); // Noncompliant
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#6930 was closed prematurely.

Property = default(T);
Property.GetType(); // Compliant
}
Expand Down Expand Up @@ -366,7 +366,7 @@ class MyClass
public void M()
{
Property = null;
Property.ToString(); // FN https://github.com/SonarSource/sonar-dotnet/issues/6930
Property.ToString(); // Noncompliant
}
}

Expand Down Expand Up @@ -2123,7 +2123,7 @@ private void Foo()

if (Value != null) // Both branches enter here because PropertyReference is not learning from TrackedSymbol
{
Console.WriteLine(value.Length); // Noncompliant FP
Console.WriteLine(value.Length); // Compliant
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,7 @@ Public Class Program
Prop = Nothing
Dim X = Prop.HasValue ' Compliant
Prop = Nothing
Prop.GetType() ' FN https://github.com/SonarSource/sonar-dotnet/issues/6930
Prop = Nothing
Prop.GetType() ' Compliant
Prop.GetType() ' Noncompliant
End Sub
End Class

Expand Down
Loading