@@ -28,38 +28,61 @@ module SQL {
28
28
* Provides classes modelling the (API compatible) `mysql` and `mysql2` packages.
29
29
*/
30
30
private module MySql {
31
- /** Gets the package name `mysql` or `mysql2`. */
32
- string mysql ( ) { result = "mysql" or result = "mysql2" }
31
+ private DataFlow:: SourceNode mysql ( ) {
32
+ result = DataFlow:: moduleImport ( [ "mysql" , "mysql2" ] )
33
+ }
33
34
34
- /** Gets a call to `mysql.createConnection`. */
35
- DataFlow:: SourceNode createConnection ( ) {
36
- result = DataFlow:: moduleMember ( mysql ( ) , "createConnection" ) .getACall ( )
35
+ private DataFlow:: CallNode createPool ( ) {
36
+ result = mysql ( ) .getAMemberCall ( "createPool" )
37
37
}
38
38
39
39
/** Gets a call to `mysql.createPool`. */
40
- DataFlow:: SourceNode createPool ( ) {
41
- result = DataFlow:: moduleMember ( mysql ( ) , "createPool" ) .getACall ( )
40
+ private DataFlow:: SourceNode pool ( DataFlow:: TypeTracker t ) {
41
+ t .start ( ) and
42
+ result = createPool ( )
43
+ or
44
+ exists ( DataFlow:: TypeTracker t2 |
45
+ result = pool ( t2 ) .track ( t2 , t )
46
+ )
47
+ }
48
+
49
+ /** Gets a call to `mysql.createPool`. */
50
+ private DataFlow:: SourceNode pool ( ) {
51
+ result = pool ( DataFlow:: TypeTracker:: end ( ) )
52
+ }
53
+
54
+ /** Gets a call to `mysql.createConnection`. */
55
+ DataFlow:: CallNode createConnection ( ) {
56
+ result = mysql ( ) .getAMemberCall ( "createConnection" )
42
57
}
43
58
44
59
/** Gets a data flow node that contains a freshly created MySQL connection instance. */
45
- DataFlow:: SourceNode connection ( ) {
46
- result = createConnection ( )
60
+ private DataFlow:: SourceNode connection ( DataFlow:: TypeTracker t ) {
61
+ t .start ( ) and
62
+ (
63
+ result = createConnection ( )
64
+ or
65
+ result = pool ( ) .getAMethodCall ( "getConnection" ) .getABoundCallbackParameter ( 0 , 1 )
66
+ )
47
67
or
48
- result = createPool ( ) .getAMethodCall ( "getConnection" ) .getCallback ( 0 ) .getParameter ( 1 )
68
+ exists ( DataFlow:: TypeTracker t2 |
69
+ result = connection ( t2 ) .track ( t2 , t )
70
+ )
49
71
}
50
72
51
- /** A call to the MySql `query` method. */
52
- private class QueryCall extends DatabaseAccess , DataFlow:: ValueNode {
53
- override MethodCallExpr astNode ;
73
+ /** Gets a data flow node that contains a freshly created MySQL connection instance. */
74
+ DataFlow:: SourceNode connection ( ) {
75
+ result = connection ( DataFlow:: TypeTracker:: end ( ) )
76
+ }
54
77
78
+ /** A call to the MySql `query` method. */
79
+ private class QueryCall extends DatabaseAccess , DataFlow:: MethodCallNode {
55
80
QueryCall ( ) {
56
- exists ( DataFlow:: SourceNode recv | recv = createPool ( ) or recv = connection ( ) |
57
- this = recv .getAMethodCall ( "query" )
58
- )
81
+ this = [ pool ( ) , connection ( ) ] .getAMethodCall ( "query" )
59
82
}
60
83
61
84
override DataFlow:: Node getAQueryArgument ( ) {
62
- result = DataFlow :: valueNode ( astNode . getArgument ( 0 ) )
85
+ result = getArgument ( 0 )
63
86
}
64
87
}
65
88
@@ -71,18 +94,9 @@ private module MySql {
71
94
/** A call to the `escape` or `escapeId` method that performs SQL sanitization. */
72
95
class EscapingSanitizer extends SQL:: SqlSanitizer , @callexpr {
73
96
EscapingSanitizer ( ) {
74
- exists ( string esc | esc = "escape" or esc = "escapeId" |
75
- exists ( DataFlow:: SourceNode escape , MethodCallExpr mce |
76
- escape = DataFlow:: moduleMember ( mysql ( ) , esc ) or
77
- escape = connection ( ) .getAPropertyRead ( esc ) or
78
- escape = createPool ( ) .getAPropertyRead ( esc )
79
- |
80
- this = mce and
81
- mce = escape .getACall ( ) .asExpr ( ) and
82
- input = mce .getArgument ( 0 ) and
83
- output = mce
84
- )
85
- )
97
+ this = [ mysql ( ) , pool ( ) , connection ( ) ] .getAMemberCall ( [ "escape" , "escapeId" ] ) .asExpr ( ) and
98
+ input = this .( MethodCallExpr ) .getArgument ( 0 ) and
99
+ output = this
86
100
}
87
101
}
88
102
@@ -91,9 +105,8 @@ private module MySql {
91
105
string kind ;
92
106
93
107
Credentials ( ) {
94
- exists ( DataFlow:: SourceNode call , string prop |
95
- ( call = createConnection ( ) or call = createPool ( ) ) and
96
- call .asExpr ( ) .( CallExpr ) .hasOptionArgument ( 0 , prop , this ) and
108
+ exists ( string prop |
109
+ this = [ createConnection ( ) , createPool ( ) ] .getOptionArgument ( 0 , prop ) .asExpr ( ) and
97
110
(
98
111
prop = "user" and kind = "user name"
99
112
or
0 commit comments