Skip to content

Commit

Permalink
Add GetInstance tetsts and use the GetInstance method where it makes …
Browse files Browse the repository at this point in the history
…sense
  • Loading branch information
mary-georgiou-sonarsource committed Jul 9, 2024
1 parent 6213e26 commit 0e662e5
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ protected ProgramState ProcessArraySetValue(ProgramState state, IInvocationOpera
{
if (invocation.TargetMethod.Name == nameof(Array.SetValue)
&& invocation.TargetMethod.ContainingType.Is(KnownType.System_Array)
&& invocation.Instance.TrackedSymbol(state) is { } array)
&& invocation.GetInstance(state).TrackedSymbol(state) is { } array)
{
return invocation.ArgumentValue("value") is { ConstantValue.HasValue: true }
? state
Expand All @@ -74,7 +74,7 @@ protected ProgramState ProcessArraySetValue(ProgramState state, IInvocationOpera
protected ProgramState ProcessArrayInitialize(ProgramState state, IInvocationOperationWrapper invocation) =>
invocation.TargetMethod.Name == nameof(Array.Initialize)
&& invocation.TargetMethod.ContainingType.Is(KnownType.System_Array)
&& invocation.Instance.TrackedSymbol(state) is { } array
&& invocation.GetInstance(state).TrackedSymbol(state) is { } array
? state.SetSymbolConstraint(array, Hardcoded)
: null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private static ProgramState ProcessSecureRandomGetInstance(ProgramState state, I
private static ProgramState ProcessSeedingMethods(ProgramState state, IInvocationOperationWrapper invocation)
{
return (IsSetSeed() || IsAddSeedMaterial())
&& invocation.Instance.TrackedSymbol(state) is { } instance
&& invocation.GetInstance(state).TrackedSymbol(state) is { } instance
// If it is already unpredictable, do nothing.
// Seeding methods do not overwrite the state, but _mix_ it with the new value.
&& state[instance]?.HasConstraint(CryptographicSeedConstraint.Predictable) is true
Expand All @@ -143,7 +143,7 @@ bool IsAddSeedMaterial() =>
private ProgramState ProcessNextMethods(ProgramState state, IInvocationOperationWrapper invocation)
{
if ((IsSecureRandomMethod() || IsRandomGeneratorMethod())
&& invocation.Instance is { } instance
&& invocation.GetInstance(state) is { } instance
&& state[instance]?.HasConstraint(CryptographicSeedConstraint.Predictable) is true)
{
ReportIssue(invocation.WrappedOperation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public static ProgramState LearnFrom(ProgramState state, IInvocationOperationWra
{
return state.SetOperationConstraint(invocation, constraint);
}
if (invocation.Instance is { } instance && instance.Type.DerivesOrImplementsAny(CollectionTypes))
if (invocation.GetInstance(state) is { } instance && instance.Type.DerivesOrImplementsAny(CollectionTypes))
{
var targetMethod = invocation.TargetMethod;
var symbolValue = state[instance] ?? SymbolicValue.Empty;
Expand Down Expand Up @@ -182,8 +182,7 @@ private static NumberConstraint EnumerableCountConstraint(ProgramState state, II
{
if (invocation.TargetMethod.Is(KnownType.System_Linq_Enumerable, nameof(Enumerable.Count)))
{
var instance = invocation.Instance ?? invocation.Arguments[0].ToArgument().Value;
if (instance.TrackedSymbol(state) is { } symbol
if (invocation.GetInstance(state).TrackedSymbol(state) is { } symbol
&& state[symbol]?.Constraint<CollectionConstraint>() is { } collection)
{
if (collection == CollectionConstraint.Empty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ protected override ProgramState[] Process(SymbolicContext context, IInvocationOp
if (invocation.TargetMethod.IsExtensionMethod
&& invocation.TargetMethod.ReducedFrom is { } reducedFrom // VB reduces method symbol to 'instance.Extension()' without annotated ArgumentOperation
&& reducedFrom.Parameters.First().HasNotNullAttribute()
&& invocation.Instance.TrackedSymbol(state) is { } instanceSymbol)
&& invocation.GetInstance(state).TrackedSymbol(state) is { } instanceSymbol)
{
state = state.SetSymbolConstraint(instanceSymbol, ObjectConstraint.NotNull);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* SonarAnalyzer for .NET
* Copyright (C) 2015-2024 SonarSource SA
* mailto: contact AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using Microsoft.CodeAnalysis.CSharp.Syntax;
using SonarAnalyzer.SymbolicExecution.Roslyn;
using StyleCop.Analyzers.Lightup;

namespace SonarAnalyzer.Test.SymbolicExecution.Roslyn;

[TestClass]
public class IInvocationOperationExtensionsTest
{
[DataTestMethod]
[DataRow("public void Method() {}", "sample.Method()", OperationKind.FieldReference)]
[DataRow("", "this.Method()", OperationKind.InstanceReference)]
[DataRow("", "sample.ExtensionMethod()", OperationKind.FieldReference)]
[DataRow("public void Method() {}", "sample.GetSample().Method()", OperationKind.Invocation)]

public void Invocation_GetInstance_ReturnsSymbol(string definition, string invocation, OperationKind kind)
{
var code = $$"""
class Test
{
Sample sample = new Sample();
void Method() {}
void M() => {{invocation}};
}

public class Sample
{
{{definition}}
public Sample GetSample() => new Sample();
}

public static class Extensions
{
public static void ExtensionMethod(this Sample sample) {}
}
""";
var (tree, model) = TestHelper.CompileCS(code);
var invocationSyntax = tree.GetRoot().DescendantNodesAndSelf().OfType<InvocationExpressionSyntax>().First();
var operation = IInvocationOperationWrapper.FromOperation(model.GetOperation(invocationSyntax));
var d = operation.GetInstance(ProgramState.Empty);
d.Should().NotBeNull().And.BeAssignableTo<IOperation>().Which.Kind.Should().Be(kind);
}
}

0 comments on commit 0e662e5

Please sign in to comment.