@@ -28,38 +28,61 @@ module SQL {
2828 * Provides classes modelling the (API compatible) `mysql` and `mysql2` packages.
2929 */
3030private 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+ }
3334
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" )
3737 }
3838
3939 /** 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" )
4257 }
4358
4459 /** 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+ )
4767 or
48- result = createPool ( ) .getAMethodCall ( "getConnection" ) .getCallback ( 0 ) .getParameter ( 1 )
68+ exists ( DataFlow:: TypeTracker t2 |
69+ result = connection ( t2 ) .track ( t2 , t )
70+ )
4971 }
5072
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+ }
5477
78+ /** A call to the MySql `query` method. */
79+ private class QueryCall extends DatabaseAccess , DataFlow:: MethodCallNode {
5580 QueryCall ( ) {
56- exists ( DataFlow:: SourceNode recv | recv = createPool ( ) or recv = connection ( ) |
57- this = recv .getAMethodCall ( "query" )
58- )
81+ this = [ pool ( ) , connection ( ) ] .getAMethodCall ( "query" )
5982 }
6083
6184 override DataFlow:: Node getAQueryArgument ( ) {
62- result = DataFlow :: valueNode ( astNode . getArgument ( 0 ) )
85+ result = getArgument ( 0 )
6386 }
6487 }
6588
@@ -71,18 +94,9 @@ private module MySql {
7194 /** A call to the `escape` or `escapeId` method that performs SQL sanitization. */
7295 class EscapingSanitizer extends SQL:: SqlSanitizer , @callexpr {
7396 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
86100 }
87101 }
88102
@@ -91,9 +105,8 @@ private module MySql {
91105 string kind ;
92106
93107 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
97110 (
98111 prop = "user" and kind = "user name"
99112 or
0 commit comments