@@ -71,48 +71,27 @@ private module Asyncpg {
7171 * The result of calling `prepare(query)` is a `PreparedStatementFactory` and the argument, `query` needs to
7272 * be tracked to the place where a `PreparedStatement` is created and then futher to any executing methods.
7373 * Hence the two type trackers.
74- *
75- * TODO: Rewrite this, once we have `API::CallNode` available.
7674 */
7775 module PreparedStatement {
78- class PreparedStatementConstruction extends SqlConstruction:: Range , DataFlow :: CallCfgNode {
76+ class PreparedStatementConstruction extends SqlConstruction:: Range , API :: CallNode {
7977 PreparedStatementConstruction ( ) { this = connection ( ) .getMember ( "prepare" ) .getACall ( ) }
8078
81- override DataFlow:: Node getSql ( ) { result in [ this .getArg ( 0 ) , this . getArgByName ( "query" ) ] }
79+ override DataFlow:: Node getSql ( ) { result = this .getParameter ( 0 , "query" ) . getARhs ( ) }
8280 }
8381
84- private DataFlow:: TypeTrackingNode preparedStatementFactory (
85- DataFlow:: TypeTracker t , DataFlow:: Node sql
86- ) {
87- t .start ( ) and
88- sql = result .( PreparedStatementConstruction ) .getSql ( )
89- or
90- exists ( DataFlow:: TypeTracker t2 | result = preparedStatementFactory ( t2 , sql ) .track ( t2 , t ) )
91- }
92-
93- DataFlow:: Node preparedStatementFactory ( DataFlow:: Node sql ) {
94- preparedStatementFactory ( DataFlow:: TypeTracker:: end ( ) , sql ) .flowsTo ( result )
95- }
96-
97- private DataFlow:: TypeTrackingNode preparedStatement ( DataFlow:: TypeTracker t , DataFlow:: Node sql ) {
98- t .start ( ) and
99- result = awaited ( preparedStatementFactory ( sql ) )
100- or
101- exists ( DataFlow:: TypeTracker t2 | result = preparedStatement ( t2 , sql ) .track ( t2 , t ) )
102- }
103-
104- DataFlow:: Node preparedStatement ( DataFlow:: Node sql ) {
105- preparedStatement ( DataFlow:: TypeTracker:: end ( ) , sql ) .flowsTo ( result )
106- }
107-
108- class PreparedStatementExecution extends SqlExecution:: Range , DataFlow:: MethodCallNode {
109- DataFlow:: Node sql ;
82+ class PreparedStatementExecution extends SqlExecution:: Range , API:: CallNode {
83+ PreparedStatementConstruction prepareCall ;
11084
11185 PreparedStatementExecution ( ) {
112- this .calls ( preparedStatement ( sql ) , [ "executemany" , "fetch" , "fetchrow" , "fetchval" ] )
86+ this =
87+ prepareCall
88+ .getReturn ( )
89+ .getAwaited ( )
90+ .getMember ( [ "executemany" , "fetch" , "fetchrow" , "fetchval" ] )
91+ .getACall ( )
11392 }
11493
115- override DataFlow:: Node getSql ( ) { result = sql }
94+ override DataFlow:: Node getSql ( ) { result = prepareCall . getSql ( ) }
11695 }
11796 }
11897
@@ -124,37 +103,36 @@ private module Asyncpg {
124103 * The result of calling `cursor` in either case is a `CursorFactory` and the argument, `query` needs to
125104 * be tracked to the place where a `Cursor` is created, hence the type tracker.
126105 * The creation of the `Cursor` executes the query.
127- *
128- * TODO: Rewrite this, once we have `API::CallNode` available.
129106 */
130107 module Cursor {
131- class CursorConstruction extends SqlConstruction:: Range , DataFlow :: CallCfgNode {
108+ class CursorConstruction extends SqlConstruction:: Range , API :: CallNode {
132109 CursorConstruction ( ) { this = connection ( ) .getMember ( "cursor" ) .getACall ( ) }
133110
134- override DataFlow:: Node getSql ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "query" ) ] }
135- }
136-
137- private DataFlow:: TypeTrackingNode cursorFactory ( DataFlow:: TypeTracker t , DataFlow:: Node sql ) {
138- // cursor created from connection
139- t .start ( ) and
140- sql = result .( CursorConstruction ) .getSql ( )
141- or
142- // cursor created from prepared statement
143- t .start ( ) and
144- result .( DataFlow:: MethodCallNode ) .calls ( PreparedStatement:: preparedStatement ( sql ) , "cursor" )
145- or
146- exists ( DataFlow:: TypeTracker t2 | result = cursorFactory ( t2 , sql ) .track ( t2 , t ) )
147- }
148-
149- DataFlow:: Node cursorFactory ( DataFlow:: Node sql ) {
150- cursorFactory ( DataFlow:: TypeTracker:: end ( ) , sql ) .flowsTo ( result )
111+ override DataFlow:: Node getSql ( ) { result = this .getParameter ( 0 , "query" ) .getARhs ( ) }
151112 }
152113
153114 /** The creation of a `Cursor` executes the associated query. */
154115 class CursorCreation extends SqlExecution:: Range {
155116 DataFlow:: Node sql ;
156117
157- CursorCreation ( ) { this = awaited ( cursorFactory ( sql ) ) }
118+ CursorCreation ( ) {
119+ exists ( CursorConstruction c |
120+ sql = c .getSql ( ) and
121+ this = c .getReturn ( ) .getAwaited ( ) .getAnImmediateUse ( )
122+ )
123+ or
124+ exists ( PreparedStatement:: PreparedStatementConstruction prepareCall |
125+ sql = prepareCall .getSql ( ) and
126+ this =
127+ prepareCall
128+ .getReturn ( )
129+ .getAwaited ( )
130+ .getMember ( "cursor" )
131+ .getReturn ( )
132+ .getAwaited ( )
133+ .getAnImmediateUse ( )
134+ )
135+ }
158136
159137 override DataFlow:: Node getSql ( ) { result = sql }
160138 }
0 commit comments