Skip to content

Commit

Permalink
Add test cases with the latest version of EntityFrameworkCore
Browse files Browse the repository at this point in the history
  • Loading branch information
costin-zaharia-sonarsource committed Jan 21, 2022
1 parent 6377757 commit 30831af
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ public abstract class ExecutingSqlQueriesBase<TSyntaxKind, TExpressionSyntax, TI
new(KnownType.Microsoft_EntityFrameworkCore_RelationalQueryableExtensions, "FromSql")
};

private readonly MemberDescriptor[] invocationsForFirstTwoArgumentsAfterV2 =
{
new(KnownType.Microsoft_EntityFrameworkCore_RelationalDatabaseFacadeExtensions, "ExecuteSqlRaw"),
new(KnownType.Microsoft_EntityFrameworkCore_RelationalDatabaseFacadeExtensions, "ExecuteSqlRawAsync"),
new(KnownType.Microsoft_EntityFrameworkCore_RelationalQueryableExtensions, "FromSqlRaw")
};

private readonly MemberDescriptor[] invocationsForFirstArgument =
{
new(KnownType.System_Data_Sqlite_SqliteCommand, "Execute")
Expand Down Expand Up @@ -116,6 +123,11 @@ protected override void Initialize(TrackerInput input)
inv.And(MethodHasRawSqlQueryParameter(), inv.Or(ArgumentAtIndexIsTracked(0), ArgumentAtIndexIsTracked(1))),
inv.ExceptWhen(inv.ArgumentAtIndexIsConstant(0)));

inv.Track(input,
inv.MatchMethod(invocationsForFirstTwoArgumentsAfterV2),
inv.Or(ArgumentAtIndexIsTracked(0), ArgumentAtIndexIsTracked(1)),
inv.ExceptWhen(inv.ArgumentAtIndexIsConstant(0)));

TrackInvocations(input, invocationsForFirstArgument, FirstArgumentIndex);
TrackInvocations(input, invocationsForSecondArgument, SecondArgumentIndex);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,17 @@ internal static IEnumerable<MetadataReference> GetReferencesNet46(string sqlServ
#else

[TestMethod]
public void ExecutingSqlQueries_CS_NetCore() =>
builderCs.AddPaths(@"Hotspots\ExecutingSqlQueries_NetCore.cs")
public void ExecutingSqlQueries_CS_EntityFrameworkCore2() =>
builderCs.AddPaths(@"Hotspots\ExecutingSqlQueries_EntityFrameworkCore2.cs")
.WithOptions(ParseOptionsHelper.FromCSharp8)
.AddReferences(GetReferencesNetCore(Constants.DotNetCore220Version))
.AddReferences(GetReferencesNetCore("2.2.6"))
.Verify();

[TestMethod]
public void ExecutingSqlQueries_CS_EntityFrameworkCoreLatest() =>
builderCs.AddPaths(@"Hotspots\ExecutingSqlQueries_EntityFrameworkCoreLatest.cs")
.WithOptions(ParseOptionsHelper.FromCSharp8)
.AddReferences(GetReferencesNetCore(Constants.NuGetLatestVersion))
.Verify();

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<None Include="TestCasesForRuleFailure\**\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="TestCases\Hotspots\ExecutingSqlQueries_EntityFrameworkCoreLatest.cs" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System;
using Microsoft.EntityFrameworkCore;

namespace Tests.Diagnostics
{
class Program
{
private const string ConstQuery = "";

public void Foo(DbContext context, string query, int x, Guid guid, params object[] parameters)
{
context.Database.ExecuteSqlRaw($""); // Compliant
context.Database.ExecuteSqlRaw(""); // Compliant, constants are safe
context.Database.ExecuteSqlRaw(ConstQuery); // Compliant, constants are safe
context.Database.ExecuteSqlRaw("" + ""); // Compliant, constants are safe
context.Database.ExecuteSqlRaw(query); // Compliant, not concat or format
context.Database.ExecuteSqlRaw("" + query); // Noncompliant
context.Database.ExecuteSqlRaw($"", parameters); // Compliant
context.Database.ExecuteSqlRaw(query, parameters); // Compliant, not concat or format

context.Database.ExecuteSqlRaw("" + query, parameters); // Noncompliant
context.Database.ExecuteSqlRaw($"SELECT * FROM mytable WHERE mycol={query} AND mycol2={0}", parameters[0]); // Noncompliant
context.Database.ExecuteSqlRaw($"SELECT * FROM mytable WHERE mycol={query}{query}", x, guid); // Noncompliant
context.Database.ExecuteSqlRaw(@$"SELECT * FROM mytable WHERE mycol={query}{query}", x, guid); // Noncompliant
context.Database.ExecuteSqlRaw($@"SELECT * FROM mytable WHERE mycol={query}{query}", x, guid); // Noncompliant
context.Database.ExecuteSqlRaw($"SELECT * FROM mytable WHERE mycol={query}"); // Noncompliant

RelationalDatabaseFacadeExtensions.ExecuteSqlRaw(context.Database, query); // Compliant
RelationalDatabaseFacadeExtensions.ExecuteSqlRaw(context.Database, $"SELECT * FROM mytable WHERE mycol={query}{query}", x, guid); // Noncompliant

context.Database.ExecuteSqlRawAsync($""); // Compliant, constants are safe
context.Database.ExecuteSqlRawAsync(""); // Compliant, constants are safe
context.Database.ExecuteSqlRawAsync(ConstQuery); // Compliant, constants are safe
context.Database.ExecuteSqlRawAsync("" + ""); // Compliant, constants are safe
context.Database.ExecuteSqlRawAsync(query); // Compliant, not concat
context.Database.ExecuteSqlRawAsync("" + query); // Noncompliant
context.Database.ExecuteSqlRawAsync(query + ""); // Noncompliant
context.Database.ExecuteSqlRawAsync("" + query + ""); // Noncompliant
context.Database.ExecuteSqlRawAsync($"", parameters); // Compliant
context.Database.ExecuteSqlRawAsync(query, parameters); // Compliant, not concat or format

context.Database.ExecuteSqlRawAsync("" + query, parameters); // Noncompliant
RelationalDatabaseFacadeExtensions.ExecuteSqlRawAsync(context.Database, "" + query, parameters); // Noncompliant

context.Set<User>().FromSqlRaw($""); // Compliant
context.Set<User>().FromSqlRaw(""); // Compliant, constants are safe
context.Set<User>().FromSqlRaw(ConstQuery); // Compliant, constants are safe
context.Set<User>().FromSqlRaw(query); // Compliant, not concat/format
context.Set<User>().FromSqlRaw("" + ""); // Compliant
context.Set<User>().FromSqlRaw($"", parameters); // Compliant
context.Set<User>().FromSqlRaw("", parameters); // Compliant, the parameters are sanitized
context.Set<User>().FromSqlRaw(query, parameters); // Compliant
context.Set<User>().FromSqlRaw("" + query, parameters); // Noncompliant
RelationalQueryableExtensions.FromSqlRaw(context.Set<User>(), "" + query, parameters); // Noncompliant
}

public void ConcatAndFormat(DbContext context, string query, params object[] parameters)
{
var concatenated = string.Concat(query, parameters); // Secondary [1,2,3]
var formatted = string.Format("INSERT INTO Users (name) VALUES (\"{0}\")", parameters); // Secondary [4,5,6]
var interpolated = $"SELECT * FROM mytable WHERE mycol={parameters[0]}"; // Secondary [7,8,9]

context.Database.ExecuteSqlRaw(string.Concat(query, parameters)); // Noncompliant
context.Database.ExecuteSqlRaw(string.Format(query, parameters)); // Noncompliant
context.Database.ExecuteSqlRaw(string.Format("INSERT INTO Users (name) VALUES (\"{0}\")", parameters)); // Noncompliant
context.Database.ExecuteSqlRaw($"SELECT * FROM mytable WHERE mycol={parameters[0]}"); // Noncompliant
context.Database.ExecuteSqlRaw("SELECT * FROM mytable WHERE mycol=" + parameters[0]); // Noncompliant
context.Database.ExecuteSqlRaw(formatted); // Noncompliant [4]
context.Database.ExecuteSqlRaw(concatenated); // Noncompliant [1]
context.Database.ExecuteSqlRaw(interpolated); // Noncompliant [7]

context.Database.ExecuteSqlRawAsync(string.Concat(query, parameters)); // Noncompliant
context.Database.ExecuteSqlRawAsync(string.Format(query, parameters)); // Noncompliant
context.Database.ExecuteSqlRawAsync(string.Format("INSERT INTO Users (name) VALUES (\"{0}\")", parameters)); // Noncompliant
context.Database.ExecuteSqlRawAsync($"SELECT * FROM mytable WHERE mycol={parameters[0]}"); // Noncompliant
context.Database.ExecuteSqlRawAsync("SELECT * FROM mytable WHERE mycol=" + parameters[0]); // Noncompliant
context.Database.ExecuteSqlRawAsync(formatted); // Noncompliant [5]
context.Database.ExecuteSqlRawAsync(concatenated); // Noncompliant [2]
context.Database.ExecuteSqlRawAsync(interpolated); // Noncompliant [8]

context.Set<User>().FromSqlRaw(string.Concat(query, parameters)); // Noncompliant
context.Set<User>().FromSqlRaw(string.Format("INSERT INTO Users (name) VALUES (\"{0}\")", parameters)); // Noncompliant
context.Set<User>().FromSqlRaw($"SELECT * FROM mytable WHERE mycol={parameters[0]}"); // Noncompliant
context.Set<User>().FromSqlRaw("SELECT * FROM mytable WHERE mycol=" + parameters[0]); // Noncompliant
context.Set<User>().FromSqlRaw(formatted); // Noncompliant [6]
context.Set<User>().FromSqlRaw(concatenated); // Noncompliant [3]
context.Set<User>().FromSqlRaw(interpolated); // Noncompliant [9]
}
}

class User
{
string Id { get; set; }
string Name { get; set; }
}
}

0 comments on commit 30831af

Please sign in to comment.