@@ -7,91 +7,42 @@ private import python
7
7
private import semmle.python.dataflow.new.DataFlow
8
8
private import semmle.python.Concepts
9
9
private import semmle.python.ApiGraphs
10
+ private import semmle.python.frameworks.data.ModelsAsData
10
11
11
12
/** Provides models for the `asyncpg` PyPI package. */
12
13
private module Asyncpg {
13
- private import semmle.python.internal.Awaited
14
-
15
- /** Gets a `ConnectionPool` that is created when the result of `asyncpg.create_pool()` is awaited. */
16
- API:: Node connectionPool ( ) {
17
- result = API:: moduleImport ( "asyncpg" ) .getMember ( "create_pool" ) .getReturn ( ) .getAwaited ( )
18
- }
19
-
20
- /**
21
- * Gets a `Connection` that is created when
22
- * - the result of `asyncpg.connect()` is awaited.
23
- * - the result of calling `acquire` on a `ConnectionPool` is awaited.
24
- */
25
- API:: Node connection ( ) {
26
- result = API:: moduleImport ( "asyncpg" ) .getMember ( "connect" ) .getReturn ( ) .getAwaited ( )
27
- or
28
- result = connectionPool ( ) .getMember ( "acquire" ) .getReturn ( ) .getAwaited ( )
29
- }
30
-
31
- /** `Connection`s and `ConnectionPool`s provide some methods that execute SQL. */
32
- class SqlExecutionOnConnection extends SqlExecution:: Range , DataFlow:: MethodCallNode {
33
- string methodName ;
34
-
35
- SqlExecutionOnConnection ( ) {
36
- this = [ connectionPool ( ) , connection ( ) ] .getMember ( methodName ) .getACall ( ) and
37
- methodName in [ "copy_from_query" , "execute" , "fetch" , "fetchrow" , "fetchval" , "executemany" ]
38
- }
39
-
40
- override DataFlow:: Node getSql ( ) {
41
- methodName in [ "copy_from_query" , "execute" , "fetch" , "fetchrow" , "fetchval" ] and
42
- result in [ this .getArg ( 0 ) , this .getArgByName ( "query" ) ]
43
- or
44
- methodName = "executemany" and
45
- result in [ this .getArg ( 0 ) , this .getArgByName ( "command" ) ]
46
- }
47
- }
48
-
49
- /** A model of `Connection` and `ConnectionPool`, which provide some methods that access the file system. */
50
- class FileAccessOnConnection extends FileSystemAccess:: Range , DataFlow:: MethodCallNode {
51
- string methodName ;
52
-
53
- FileAccessOnConnection ( ) {
54
- this = [ connectionPool ( ) , connection ( ) ] .getMember ( methodName ) .getACall ( ) and
55
- methodName in [ "copy_from_query" , "copy_from_table" , "copy_to_table" ]
56
- }
57
-
58
- // The path argument is keyword only.
59
- override DataFlow:: Node getAPathArgument ( ) {
60
- methodName in [ "copy_from_query" , "copy_from_table" ] and
61
- result = this .getArgByName ( "output" )
62
- or
63
- methodName = "copy_to_table" and
64
- result = this .getArgByName ( "source" )
14
+ class AsyncpgModel extends ModelInput:: TypeModelCsv {
15
+ override predicate row ( string row ) {
16
+ // package1;type1;package2;type2;path
17
+ row =
18
+ [
19
+ // a `ConnectionPool` that is created when the result of `asyncpg.create_pool()` is awaited.
20
+ "asyncpg;ConnectionPool;asyncpg;;Member[create_pool].ReturnValue.Awaited" ,
21
+ // a `Connection` that is created when
22
+ // * - the result of `asyncpg.connect()` is awaited.
23
+ // * - the result of calling `acquire` on a `ConnectionPool` is awaited.
24
+ "asyncpg;Connection;asyncpg;;Member[connect].ReturnValue.Awaited" ,
25
+ "asyncpg;Connection;asyncpg;ConnectionPool;Member[acquire].ReturnValue.Awaited" ,
26
+ // Creating an internal `~Connection` type that contains both `Connection` and `ConnectionPool`.
27
+ "asyncpg;~Connection;asyncpg;Connection;" , "asyncpg;~Connection;asyncpg;ConnectionPool;"
28
+ ]
65
29
}
66
30
}
67
31
68
- /**
69
- * Provides models of the `PreparedStatement` class in `asyncpg`.
70
- * `PreparedStatement`s are created when the result of calling `prepare(query)` on a connection is awaited.
71
- * The result of calling `prepare(query)` is a `PreparedStatementFactory` and the argument, `query` needs to
72
- * be tracked to the place where a `PreparedStatement` is created and then further to any executing methods.
73
- * Hence the two type trackers.
74
- */
75
- module PreparedStatement {
76
- class PreparedStatementConstruction extends SqlConstruction:: Range , API:: CallNode {
77
- PreparedStatementConstruction ( ) { this = connection ( ) .getMember ( "prepare" ) .getACall ( ) }
78
-
79
- override DataFlow:: Node getSql ( ) { result = this .getParameter ( 0 , "query" ) .getARhs ( ) }
80
- }
81
-
82
- class PreparedStatementExecution extends SqlExecution:: Range , API:: CallNode {
83
- PreparedStatementConstruction prepareCall ;
84
-
85
- PreparedStatementExecution ( ) {
86
- this =
87
- prepareCall
88
- .getReturn ( )
89
- .getAwaited ( )
90
- .getMember ( [ "executemany" , "fetch" , "fetchrow" , "fetchval" ] )
91
- .getACall ( )
92
- }
93
-
94
- override DataFlow:: Node getSql ( ) { result = prepareCall .getSql ( ) }
32
+ class AsyncpgSink extends ModelInput:: SinkModelCsv {
33
+ // package;type;path;kind
34
+ override predicate row ( string row ) {
35
+ row =
36
+ [
37
+ // `Connection`s and `ConnectionPool`s provide some methods that execute SQL.
38
+ "asyncpg;~Connection;Member[copy_from_query,execute,fetch,fetchrow,fetchval].Argument[0,query:];sql-injection" ,
39
+ "asyncpg;~Connection;Member[executemany].Argument[0,command:];sql-injection" ,
40
+ // A model of `Connection` and `ConnectionPool`, which provide some methods that access the file system.
41
+ "asyncpg;~Connection;Member[copy_from_query,copy_from_table].Argument[output:];path-injection" ,
42
+ "asyncpg;~Connection;Member[copy_to_table].Argument[source:];path-injection" ,
43
+ // the `PreparedStatement` class in `asyncpg`.
44
+ "asyncpg;Connection;Member[prepare].Argument[0,query:];sql-injection" ,
45
+ ]
95
46
}
96
47
}
97
48
@@ -106,7 +57,9 @@ private module Asyncpg {
106
57
*/
107
58
module Cursor {
108
59
class CursorConstruction extends SqlConstruction:: Range , API:: CallNode {
109
- CursorConstruction ( ) { this = connection ( ) .getMember ( "cursor" ) .getACall ( ) }
60
+ CursorConstruction ( ) {
61
+ this = ModelOutput:: getATypeNode ( "asyncpg" , "Connection" ) .getMember ( "cursor" ) .getACall ( )
62
+ }
110
63
111
64
override DataFlow:: Node getSql ( ) { result = this .getParameter ( 0 , "query" ) .getARhs ( ) }
112
65
}
@@ -121,8 +74,11 @@ private module Asyncpg {
121
74
this = c .getReturn ( ) .getAwaited ( ) .getAnImmediateUse ( )
122
75
)
123
76
or
124
- exists ( PreparedStatement:: PreparedStatementConstruction prepareCall |
125
- sql = prepareCall .getSql ( ) and
77
+ exists ( API:: CallNode prepareCall |
78
+ prepareCall =
79
+ ModelOutput:: getATypeNode ( "asyncpg" , "Connection" ) .getMember ( "prepare" ) .getACall ( )
80
+ |
81
+ sql = prepareCall .getParameter ( 0 , "query" ) .getARhs ( ) and
126
82
this =
127
83
prepareCall
128
84
.getReturn ( )
0 commit comments