Skip to content

Commit f2e28c3

Browse files
authored
Merge pull request github#9180 from hvitved/csharp/entity-framework-sql-sinks
C#: Add missing EntityFramework SQL sinks
2 parents 350d137 + 15449b7 commit f2e28c3

File tree

8 files changed

+262
-198
lines changed

8 files changed

+262
-198
lines changed

csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,30 @@ module EntityFramework {
258258
}
259259
}
260260

261+
/** A sink method in `Microsoft.EntityFrameworkCore.RelationalQueryableExtensions` that executes SQL. */
262+
private class MicrosoftEntityFrameworkCoreRelationalQueryableExtensionsSinkModelCsv extends SinkModelCsv {
263+
override predicate row(string row) {
264+
row =
265+
[
266+
"Microsoft.EntityFrameworkCore;RelationalQueryableExtensions;false;FromSqlRaw<>;(Microsoft.EntityFrameworkCore.DbSet<TEntity>,System.String,System.Object[]);;Argument[1];sql",
267+
]
268+
}
269+
}
270+
271+
/** A sink method in `Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions` that executes SQL. */
272+
private class MicrosoftEntityFrameworkCoreRelationalDatabaseFacadeExtensionsSinkModelCsv extends SinkModelCsv {
273+
override predicate row(string row) {
274+
row =
275+
[
276+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRaw;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Collections.Generic.IEnumerable<System.Object>);;Argument[1];sql",
277+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRaw;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Object[]);;Argument[1];sql",
278+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Threading.CancellationToken);;Argument[1];sql",
279+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Object[]);;Argument[1];sql",
280+
"Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;false;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Collections.Generic.IEnumerable<System.Object>,System.Threading.CancellationToken);;Argument[1];sql",
281+
]
282+
}
283+
}
284+
261285
/** Holds if `t` is compatible with a DB column type. */
262286
private predicate isColumnType(Type t) {
263287
t instanceof SimpleType

csharp/ql/test/library-tests/frameworks/EntityFramework/Dataflow.expected

Lines changed: 186 additions & 186 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/frameworks/EntityFramework/EntityFrameworkCore.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void FlowSources()
5656

5757
Microsoft.EntityFrameworkCore.Storage.IRawSqlCommandBuilder builder;
5858

59-
async void SqlExprs(MyContext ctx)
59+
async void SqlExprs(MyContext ctx, System.Threading.CancellationToken token)
6060
{
6161
// Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlCommand
6262
ctx.Database.ExecuteSqlCommand(""); // SqlExpr
@@ -68,6 +68,13 @@ async void SqlExprs(MyContext ctx)
6868
// Microsoft.EntityFrameworkCore.RawSqlString
6969
new RawSqlString(""); // SqlExpr
7070
RawSqlString str = ""; // SqlExpr
71+
72+
ctx.Persons.FromSqlRaw("sql");
73+
ctx.Database.ExecuteSqlRaw("sql", (IEnumerable<object>)null);
74+
ctx.Database.ExecuteSqlRaw("sql");
75+
await ctx.Database.ExecuteSqlRawAsync("sql", token);
76+
await ctx.Database.ExecuteSqlRawAsync("sql");
77+
await ctx.Database.ExecuteSqlRawAsync("sql", (IEnumerable<object>)null, token);
7178
}
7279

7380
void TestRawSqlStringDataFlow()

csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
summary
12
| Microsoft.EntityFrameworkCore;DbContext;false;SaveChanges;();;Argument[Qualifier].Property[EFCoreTests.MyContext.Addresses].Element.Property[EFCoreTests.Address.Id];ReturnValue[jump to get_Addresses].Element.Property[EFCoreTests.Address.Id];value |
23
| Microsoft.EntityFrameworkCore;DbContext;false;SaveChanges;();;Argument[Qualifier].Property[EFCoreTests.MyContext.Addresses].Element.Property[EFCoreTests.Address.Id];ReturnValue[jump to get_PersonAddresses].Element.Property[EFCoreTests.PersonAddressMap.Address].Property[EFCoreTests.Address.Id];value |
34
| Microsoft.EntityFrameworkCore;DbContext;false;SaveChanges;();;Argument[Qualifier].Property[EFCoreTests.MyContext.Addresses].Element.Property[EFCoreTests.Address.Id];ReturnValue[jump to get_Persons].Element.Property[EFCoreTests.Person.Addresses].Element.Property[EFCoreTests.Address.Id];value |
@@ -130,3 +131,11 @@
130131
| System.Data.Entity;DbSet<>;false;AttachRange;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[Qualifier].Element;value |
131132
| System.Data.Entity;DbSet<>;false;Update;(T);;Argument[0];Argument[Qualifier].Element;value |
132133
| System.Data.Entity;DbSet<>;false;UpdateRange;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[Qualifier].Element;value |
134+
sourceNode
135+
sinkNode
136+
| EntityFrameworkCore.cs:72:36:72:40 | "sql" | sql |
137+
| EntityFrameworkCore.cs:73:40:73:44 | "sql" | sql |
138+
| EntityFrameworkCore.cs:74:40:74:44 | "sql" | sql |
139+
| EntityFrameworkCore.cs:75:51:75:55 | "sql" | sql |
140+
| EntityFrameworkCore.cs:76:51:76:55 | "sql" | sql |
141+
| EntityFrameworkCore.cs:77:51:77:55 | "sql" | sql |
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import semmle.code.csharp.frameworks.EntityFramework::EntityFramework
22
import shared.FlowSummaries
3+
import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow
34

45
private class IncludeEFSummarizedCallable extends IncludeSummarizedCallable {
56
IncludeEFSummarizedCallable() { this instanceof EFSummarizedCallable }
67
}
8+
9+
query predicate sourceNode(DataFlow::Node node, string kind) {
10+
ExternalFlow::sourceNode(node, kind)
11+
}
12+
13+
query predicate sinkNode(DataFlow::Node node, string kind) { ExternalFlow::sinkNode(node, kind) }

csharp/ql/test/library-tests/frameworks/EntityFramework/SqlExprs.expected

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,11 @@
33
| EntityFrameworkCore.cs:66:13:66:29 | call to method Build |
44
| EntityFrameworkCore.cs:69:13:69:32 | object creation of type RawSqlString |
55
| EntityFrameworkCore.cs:70:32:70:33 | call to operator implicit conversion |
6-
| EntityFrameworkCore.cs:77:18:77:46 | object creation of type RawSqlString |
7-
| EntityFrameworkCore.cs:78:18:78:42 | call to operator implicit conversion |
6+
| EntityFrameworkCore.cs:72:13:72:41 | call to method FromSqlRaw<Person> |
7+
| EntityFrameworkCore.cs:73:13:73:72 | call to method ExecuteSqlRaw |
8+
| EntityFrameworkCore.cs:74:13:74:45 | call to method ExecuteSqlRaw |
9+
| EntityFrameworkCore.cs:75:19:75:63 | call to method ExecuteSqlRawAsync |
10+
| EntityFrameworkCore.cs:76:19:76:56 | call to method ExecuteSqlRawAsync |
11+
| EntityFrameworkCore.cs:77:19:77:90 | call to method ExecuteSqlRawAsync |
12+
| EntityFrameworkCore.cs:84:18:84:46 | object creation of type RawSqlString |
13+
| EntityFrameworkCore.cs:85:18:85:42 | call to operator implicit conversion |

csharp/ql/test/library-tests/frameworks/EntityFramework/StoredFlowSources.expected

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
| EntityFramework.cs:219:18:219:61 | access to property Street |
1111
| EntityFrameworkCore.cs:52:22:52:25 | access to property Id |
1212
| EntityFrameworkCore.cs:53:24:53:29 | access to property Name |
13-
| EntityFrameworkCore.cs:229:18:229:39 | access to property Id |
14-
| EntityFrameworkCore.cs:230:18:230:41 | access to property Name |
15-
| EntityFrameworkCore.cs:237:18:237:41 | access to property Id |
16-
| EntityFrameworkCore.cs:238:18:238:45 | access to property Street |
17-
| EntityFrameworkCore.cs:244:18:244:46 | access to property Addresses |
18-
| EntityFrameworkCore.cs:244:18:244:57 | access to property Id |
19-
| EntityFrameworkCore.cs:245:18:245:46 | access to property Addresses |
20-
| EntityFrameworkCore.cs:245:18:245:61 | access to property Street |
13+
| EntityFrameworkCore.cs:236:18:236:39 | access to property Id |
14+
| EntityFrameworkCore.cs:237:18:237:41 | access to property Name |
15+
| EntityFrameworkCore.cs:244:18:244:41 | access to property Id |
16+
| EntityFrameworkCore.cs:245:18:245:45 | access to property Street |
17+
| EntityFrameworkCore.cs:251:18:251:46 | access to property Addresses |
18+
| EntityFrameworkCore.cs:251:18:251:57 | access to property Id |
19+
| EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses |
20+
| EntityFrameworkCore.cs:252:18:252:61 | access to property Street |

csharp/ql/test/resources/stubs/EntityFramework.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,16 @@ public class DatabaseFacade
8888
}
8989
}
9090

91-
public static class RelationalDatabaseFacaseExtensions
91+
public static class RelationalDatabaseFacadeExtensions
9292
{
9393
public static void ExecuteSqlCommand(this Infrastructure.DatabaseFacade db, string sql, params object[] parameters) { }
9494
public static Task ExecuteSqlCommandAsync(this Infrastructure.DatabaseFacade db, string sql, params object[] parameters) => throw null;
95+
96+
public static int ExecuteSqlRaw(this Infrastructure.DatabaseFacade db, string sql, IEnumerable<object> args) => throw null;
97+
public static int ExecuteSqlRaw(this Infrastructure.DatabaseFacade db, string sql, params object[] args) => throw null;
98+
public static Task<int> ExecuteSqlRawAsync(this Infrastructure.DatabaseFacade db, string sql, System.Threading.CancellationToken token) => throw null;
99+
public static Task<int> ExecuteSqlRawAsync(this Infrastructure.DatabaseFacade db, string sql, params object[] args) => throw null;
100+
public static Task<int> ExecuteSqlRawAsync(this Infrastructure.DatabaseFacade db, string sql, IEnumerable<object> args, System.Threading.CancellationToken token) => throw null;
95101
}
96102

97103
struct RawSqlString
@@ -100,6 +106,11 @@ public RawSqlString(string str) { }
100106
public static implicit operator Microsoft.EntityFrameworkCore.RawSqlString(FormattableString fs) => throw null;
101107
public static implicit operator Microsoft.EntityFrameworkCore.RawSqlString(string s) => throw null;
102108
}
109+
110+
public static class RelationalQueryableExtensions
111+
{
112+
public static void FromSqlRaw<TEntity>(this DbSet<TEntity> set, string sql, params object[] args) => throw null;
113+
}
103114
}
104115

105116
namespace Microsoft.EntityFrameworkCore.Storage

0 commit comments

Comments
 (0)