@@ -79,6 +79,31 @@ module PEP249 {
7979 * See https://www.python.org/dev/peps/pep-0249/#cursor.
8080 */
8181 module cursor {
82+ /**
83+ * A source of database cursors (following PEP 249), extend this class to model new instances.
84+ *
85+ * This can include instantiations of the class, return values from function
86+ * calls, or a special parameter that will be set when functions are called by external
87+ * libraries.
88+ *
89+ * Use the predicate `Connection::instance()` to get references database cursors (following PEP 249).
90+ *
91+ * Extend this class if the module implementing PEP 249 offers more direct ways to obtain
92+ * a connection than going through `connect`.
93+ */
94+ abstract class InstanceSource extends DataFlow:: LocalSourceNode { }
95+
96+ /** Gets a reference to a database cursor. */
97+ private DataFlow:: LocalSourceNode instance ( DataFlow:: TypeTracker t ) {
98+ t .start ( ) and
99+ result instanceof InstanceSource
100+ or
101+ exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
102+ }
103+
104+ /** Gets a reference to a database cursor. */
105+ DataFlow:: Node instance ( ) { instance ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
106+
82107 /** Gets a reference to the `cursor` method on a database connection. */
83108 private DataFlow:: LocalSourceNode methodRef ( DataFlow:: TypeTracker t ) {
84109 t .startInAttr ( "cursor" ) and
@@ -90,6 +115,11 @@ module PEP249 {
90115 /** Gets a reference to the `cursor` method on a database connection. */
91116 DataFlow:: Node methodRef ( ) { methodRef ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
92117
118+ /** A call to the `cursor` method on a database connection */
119+ private class CursorCall extends InstanceSource , DataFlow:: CallCfgNode {
120+ CursorCall ( ) { this .getFunction ( ) = methodRef ( ) }
121+ }
122+
93123 /** Gets a reference to a result of calling the `cursor` method on a database connection. */
94124 private DataFlow:: LocalSourceNode methodResult ( DataFlow:: TypeTracker t ) {
95125 t .start ( ) and
@@ -98,8 +128,14 @@ module PEP249 {
98128 exists ( DataFlow:: TypeTracker t2 | result = methodResult ( t2 ) .track ( t2 , t ) )
99129 }
100130
101- /** Gets a reference to a result of calling the `cursor` method on a database connection. */
102- DataFlow:: Node methodResult ( ) { methodResult ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
131+ /**
132+ * DEPRECATED: Use `Cursor::instance()` to get references to database cursors instead.
133+ *
134+ * Gets a reference to a result of calling the `cursor` method on a database connection.
135+ */
136+ deprecated DataFlow:: Node methodResult ( ) {
137+ methodResult ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result )
138+ }
103139 }
104140
105141 /**
@@ -112,7 +148,7 @@ module PEP249 {
112148 */
113149 private DataFlow:: LocalSourceNode execute ( DataFlow:: TypeTracker t ) {
114150 t .startInAttr ( "execute" ) and
115- result in [ cursor:: methodResult ( ) , Connection:: instance ( ) ]
151+ result in [ cursor:: instance ( ) , Connection:: instance ( ) ]
116152 or
117153 exists ( DataFlow:: TypeTracker t2 | result = execute ( t2 ) .track ( t2 , t ) )
118154 }
0 commit comments