mirror of
https://github.com/github/codeql.git
synced 2026-04-25 08:45:14 +02:00
Merge pull request #6161 from RasmusWL/peewee-modeling
Python: Add modeling of `peewee`
This commit is contained in:
@@ -176,6 +176,7 @@ Python built-in support
|
||||
mysqlclient, Database
|
||||
psycopg2, Database
|
||||
sqlite3, Database
|
||||
peewee, Database ORM
|
||||
cryptography, Cryptography library
|
||||
pycryptodome, Cryptography library
|
||||
pycryptodomex, Cryptography library
|
||||
|
||||
2
python/change-notes/2021-06-25-add-peewee-modeling.md
Normal file
2
python/change-notes/2021-06-25-add-peewee-modeling.md
Normal file
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* Added modeling of raw SQL execution from the PyPI package `peewee`.
|
||||
@@ -26,6 +26,7 @@ private import semmle.python.frameworks.Rsa
|
||||
private import semmle.python.frameworks.Simplejson
|
||||
private import semmle.python.frameworks.Stdlib
|
||||
private import semmle.python.frameworks.Tornado
|
||||
private import semmle.python.frameworks.Peewee
|
||||
private import semmle.python.frameworks.Twisted
|
||||
private import semmle.python.frameworks.Ujson
|
||||
private import semmle.python.frameworks.Yaml
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
private import python
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
private import semmle.python.frameworks.PEP249
|
||||
private import semmle.python.frameworks.ClickhouseDriver
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,7 @@ module ClickhouseDriver {
|
||||
* `clickhouse_driver` implements PEP249,
|
||||
* providing ways to execute SQL statements against a database.
|
||||
*/
|
||||
class ClickHouseDriverPEP249 extends PEP249ModuleApiNode {
|
||||
class ClickHouseDriverPEP249 extends PEP249::PEP249ModuleApiNode {
|
||||
ClickHouseDriverPEP249() { this = API::moduleImport("clickhouse_driver") }
|
||||
}
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ private module PrivateDjango {
|
||||
/**
|
||||
* `django.db` implements PEP249, providing ways to execute SQL statements against a database.
|
||||
*/
|
||||
private class DjangoDb extends PEP249ModuleApiNode {
|
||||
private class DjangoDb extends PEP249::PEP249ModuleApiNode {
|
||||
DjangoDb() { this = API::moduleImport("django").getMember("db") }
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ private module PrivateDjango {
|
||||
/** Gets a reference to the `django.db.connection` object. */
|
||||
API::Node connection() { result = db().getMember("connection") }
|
||||
|
||||
class DjangoDbConnection extends Connection::InstanceSource {
|
||||
class DjangoDbConnection extends PEP249::Connection::InstanceSource {
|
||||
DjangoDbConnection() { this = connection().getAUse() }
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ private module MySQLdb {
|
||||
// MySQLdb
|
||||
// ---------------------------------------------------------------------------
|
||||
/** MySQLdb implements PEP 249, providing ways to execute SQL statements against a database. */
|
||||
class MySQLdb extends PEP249ModuleApiNode {
|
||||
class MySQLdb extends PEP249::PEP249ModuleApiNode {
|
||||
MySQLdb() { this = API::moduleImport("MySQLdb") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ private module Mysql {
|
||||
* The mysql.connector module
|
||||
* See https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html
|
||||
*/
|
||||
class MysqlConnector extends PEP249ModuleApiNode {
|
||||
class MysqlConnector extends PEP249::PEP249ModuleApiNode {
|
||||
MysqlConnector() { this = API::moduleImport("mysql").getMember("connector") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,119 +8,36 @@ private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
import semmle.python.frameworks.internal.PEP249Impl
|
||||
|
||||
/**
|
||||
* A module implementing PEP 249. Extend this class for implementations.
|
||||
*
|
||||
* DEPRECATED: Extend `PEP249ModuleApiNode` instead.
|
||||
* DEPRECATED: Extend `PEP249::PEP249ModuleApiNode` instead.
|
||||
*/
|
||||
abstract deprecated class PEP249Module extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* An abstract class encompassing API graph nodes that implement PEP 249.
|
||||
* Extend this class for implementations.
|
||||
* DEPRECATED: Use `PEP249::PEP249ModuleApiNode` instead.
|
||||
*/
|
||||
abstract class PEP249ModuleApiNode extends API::Node {
|
||||
/** Gets a string representation of this element. */
|
||||
override string toString() { result = this.(API::Node).toString() }
|
||||
}
|
||||
|
||||
/** Gets a reference to a connect call. */
|
||||
DataFlow::Node connect() { result = any(PEP249ModuleApiNode a).getMember("connect").getAUse() }
|
||||
deprecated class PEP249ModuleApiNode = PEP249::PEP249ModuleApiNode;
|
||||
|
||||
/**
|
||||
* Provides models for the `db.Connection` class
|
||||
*
|
||||
* See https://www.python.org/dev/peps/pep-0249/#connection-objects.
|
||||
* DEPRECATED: Use `PEP249::Connection` instead.
|
||||
*/
|
||||
module Connection {
|
||||
/**
|
||||
* A source of instances of `db.Connection`, extend this class to model new instances.
|
||||
*
|
||||
* This can include instantiations of the class, return values from function
|
||||
* calls, or a special parameter that will be set when functions are called by external
|
||||
* libraries.
|
||||
*
|
||||
* Use the predicate `Connection::instance()` to get references to instances of `db.Connection`.
|
||||
*
|
||||
* Extend this class if the module implementing PEP 249 offers more direct ways to obtain
|
||||
* a connection than going through `connect`.
|
||||
*/
|
||||
abstract class InstanceSource extends DataFlow::Node { }
|
||||
|
||||
/** A direct instantiation of `db.Connection`. */
|
||||
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
|
||||
ClassInstantiation() { this.getFunction() = connect() }
|
||||
}
|
||||
|
||||
/** Gets a reference to an instance of `db.Connection`. */
|
||||
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result instanceof InstanceSource
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to an instance of `db.Connection`. */
|
||||
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
}
|
||||
deprecated module Connection = PEP249::Connection;
|
||||
|
||||
/**
|
||||
* Provides models for the `cursor` method on a connection.
|
||||
* See https://www.python.org/dev/peps/pep-0249/#cursor.
|
||||
* DEPRECATED: Use `PEP249::Cursor` instead.
|
||||
*/
|
||||
module cursor {
|
||||
/** Gets a reference to the `cursor` method on a connection. */
|
||||
private DataFlow::TypeTrackingNode methodRef(DataFlow::TypeTracker t) {
|
||||
t.startInAttr("cursor") and
|
||||
result = Connection::instance()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = methodRef(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `cursor` method on a connection. */
|
||||
DataFlow::Node methodRef() { methodRef(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
|
||||
/** Gets a reference to a result of calling the `cursor` method on a connection. */
|
||||
private DataFlow::TypeTrackingNode methodResult(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result.asCfgNode().(CallNode).getFunction() = methodRef().asCfgNode()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = methodResult(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to a result of calling the `cursor` method on a connection. */
|
||||
DataFlow::Node methodResult() { methodResult(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
}
|
||||
deprecated module cursor = PEP249::Cursor;
|
||||
|
||||
/**
|
||||
* Gets a reference to the `execute` method on a cursor (or on a connection).
|
||||
*
|
||||
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
|
||||
* recognize it as an alias for constructing a cursor and calling `execute` on it.
|
||||
*
|
||||
* See https://www.python.org/dev/peps/pep-0249/#id15.
|
||||
* DEPRECATED: Use `PEP249::execute` instead.
|
||||
*/
|
||||
private DataFlow::TypeTrackingNode execute(DataFlow::TypeTracker t) {
|
||||
t.startInAttr("execute") and
|
||||
result in [cursor::methodResult(), Connection::instance()]
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = execute(t2).track(t2, t))
|
||||
}
|
||||
deprecated predicate execute = PEP249::execute/0;
|
||||
|
||||
/**
|
||||
* Gets a reference to the `execute` method on a cursor (or on a connection).
|
||||
*
|
||||
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
|
||||
* recognize it as an alias for constructing a cursor and calling `execute` on it.
|
||||
*
|
||||
* See https://www.python.org/dev/peps/pep-0249/#id15.
|
||||
* DEPRECATED: Use `PEP249::connect` instead.
|
||||
*/
|
||||
DataFlow::Node execute() { execute(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
|
||||
/** A call to the `execute` method on a cursor (or on a connection). */
|
||||
private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode {
|
||||
ExecuteCall() { this.getFunction() = execute() }
|
||||
|
||||
override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] }
|
||||
}
|
||||
deprecated predicate connect = PEP249::connect/0;
|
||||
|
||||
192
python/ql/src/semmle/python/frameworks/Peewee.qll
Normal file
192
python/ql/src/semmle/python/frameworks/Peewee.qll
Normal file
@@ -0,0 +1,192 @@
|
||||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `peewee` PyPI package.
|
||||
* See
|
||||
* - https://pypi.org/project/peewee/
|
||||
* - https://docs.peewee-orm.com/en/latest/index.html
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.TaintTracking
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
private import semmle.python.frameworks.PEP249
|
||||
|
||||
/**
|
||||
* Provides models for the `peewee` PyPI package.
|
||||
* See
|
||||
* - https://pypi.org/project/peewee/
|
||||
* - https://docs.peewee-orm.com/en/latest/index.html
|
||||
*/
|
||||
private module Peewee {
|
||||
/** Provides models for the `peewee.Database` class and subclasses. */
|
||||
module Database {
|
||||
/** Gets a reference to the `peewee.Database` class or any subclass. */
|
||||
API::Node subclassRef() {
|
||||
result = API::moduleImport("peewee").getMember("Database").getASubclass*()
|
||||
or
|
||||
// known subclasses
|
||||
result =
|
||||
API::moduleImport("peewee")
|
||||
.getMember(["SqliteDatabase", "MySQLDatabase", "PostgresqlDatabase"])
|
||||
.getASubclass*()
|
||||
or
|
||||
// Ohter known subclasses, semi auto generated by using
|
||||
// ```codeql
|
||||
// class DBClass extends Class, SelfRefMixin {
|
||||
// DBClass() {
|
||||
// exists(this.getLocation().getFile().getRelativePath()) and
|
||||
// this.getName().matches("%Database") and
|
||||
// this.getABase().(Name).getId().matches("%Database")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// from DBClass dbClass, Module mod
|
||||
// where
|
||||
// dbClass.getScope() = mod
|
||||
// select mod.getName()+ "." + dbClass.getName()
|
||||
// ```
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("apsw_ext")
|
||||
.getMember("APSWDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("cockroachdb")
|
||||
.getMember("CockroachDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("cockroachdb")
|
||||
.getMember("PooledCockroachDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("mysql_ext")
|
||||
.getMember("MySQLConnectorDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("pool")
|
||||
.getMember("PooledCSqliteExtDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("pool")
|
||||
.getMember("PooledMySQLDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("pool")
|
||||
.getMember("PooledPostgresqlDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("pool")
|
||||
.getMember("PooledPostgresqlExtDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("pool")
|
||||
.getMember("PooledSqliteDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("pool")
|
||||
.getMember("PooledSqliteExtDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("pool")
|
||||
.getMember("_PooledPostgresqlDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("pool")
|
||||
.getMember("_PooledSqliteDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("postgres_ext")
|
||||
.getMember("PostgresqlExtDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("sqlcipher_ext")
|
||||
.getMember("SqlCipherDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("sqlcipher_ext")
|
||||
.getMember("SqlCipherExtDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("sqlite_ext")
|
||||
.getMember("CSqliteExtDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("sqlite_ext")
|
||||
.getMember("SqliteExtDatabase")
|
||||
.getASubclass*()
|
||||
or
|
||||
result =
|
||||
API::moduleImport("playhouse")
|
||||
.getMember("sqliteq")
|
||||
.getMember("SqliteQueueDatabase")
|
||||
.getASubclass*()
|
||||
}
|
||||
|
||||
/** Gets a reference to an instance of `peewee.Database` or any subclass. */
|
||||
API::Node instance() { result = subclassRef().getReturn() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `connection` method on a `peewee.Database` instance.
|
||||
* https://docs.peewee-orm.com/en/latest/peewee/api.html#Database.connection.
|
||||
*/
|
||||
class PeeweeDatabaseConnectionCall extends PEP249::Connection::InstanceSource,
|
||||
DataFlow::CallCfgNode {
|
||||
PeeweeDatabaseConnectionCall() {
|
||||
this = Database::instance().getMember("connection").getACall()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `cursor` method on a `peewee.Database` instance.
|
||||
* https://docs.peewee-orm.com/en/latest/peewee/api.html#Database.cursor.
|
||||
*/
|
||||
class PeeweeDatabaseCursorCall extends PEP249::Cursor::InstanceSource, DataFlow::CallCfgNode {
|
||||
PeeweeDatabaseCursorCall() { this = Database::instance().getMember("cursor").getACall() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `execute_sql` method on a `peewee.Database` instance.
|
||||
* See https://docs.peewee-orm.com/en/latest/peewee/api.html#Database.execute_sql.
|
||||
*/
|
||||
class PeeweeDatabaseExecuteSqlCall extends SqlExecution::Range, DataFlow::CallCfgNode {
|
||||
PeeweeDatabaseExecuteSqlCall() {
|
||||
this = Database::instance().getMember("execute_sql").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] }
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ private module Psycopg2 {
|
||||
// Psycopg
|
||||
// ---------------------------------------------------------------------------
|
||||
/** psycopg2 implements PEP 249, providing ways to execute SQL statements against a database. */
|
||||
class Psycopg2 extends PEP249ModuleApiNode {
|
||||
class Psycopg2 extends PEP249::PEP249ModuleApiNode {
|
||||
Psycopg2() { this = API::moduleImport("psycopg2") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ private import semmle.python.frameworks.PEP249
|
||||
*/
|
||||
private module PyMySQL {
|
||||
/** PyMySQL implements PEP 249, providing ways to execute SQL statements against a database. */
|
||||
class PyMySQLPEP249 extends PEP249ModuleApiNode {
|
||||
class PyMySQLPEP249 extends PEP249::PEP249ModuleApiNode {
|
||||
PyMySQLPEP249() { this = API::moduleImport("pymysql") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -936,7 +936,7 @@ private module Stdlib {
|
||||
*
|
||||
* See https://devdocs.io/python~3.9/library/sqlite3
|
||||
*/
|
||||
class Sqlite3 extends PEP249ModuleApiNode {
|
||||
class Sqlite3 extends PEP249::PEP249ModuleApiNode {
|
||||
Sqlite3() { this = API::moduleImport("sqlite3") }
|
||||
}
|
||||
|
||||
|
||||
172
python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll
Normal file
172
python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Provides internal implementation of PEP249. This currently resides in a different
|
||||
* file than `python/ql/src/semmle/python/frameworks/PEP249.qll`, since we used to
|
||||
* export everything without being encapsulated in a module, and shadowing rules means
|
||||
* that we can't just add the module directly to that file :(
|
||||
*
|
||||
* So once we can remove those deprecated things (Start of July 2022), we can also move
|
||||
* the core implementation into its' proper place.
|
||||
*
|
||||
* Provides classes modeling PEP 249.
|
||||
* See https://www.python.org/dev/peps/pep-0249/.
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
|
||||
/**
|
||||
* Provides classes modeling database interfaces following PEP 249.
|
||||
* See https://www.python.org/dev/peps/pep-0249/.
|
||||
*/
|
||||
module PEP249 {
|
||||
/**
|
||||
* An API graph node representing a module that implements PEP 249.
|
||||
*/
|
||||
abstract class PEP249ModuleApiNode extends API::Node {
|
||||
/** Gets a string representation of this element. */
|
||||
override string toString() { result = this.(API::Node).toString() }
|
||||
}
|
||||
|
||||
/** Gets a reference to the `connect` function of a module that implements PEP 249. */
|
||||
DataFlow::Node connect() { result = any(PEP249ModuleApiNode a).getMember("connect").getAUse() }
|
||||
|
||||
/**
|
||||
* Provides models for database connections (following PEP 249).
|
||||
*
|
||||
* See https://www.python.org/dev/peps/pep-0249/#connection-objects.
|
||||
*/
|
||||
module Connection {
|
||||
/**
|
||||
* A source of database connections (following PEP 249), extend this class to model new instances.
|
||||
*
|
||||
* This can include instantiations of the class, return values from function
|
||||
* calls, or a special parameter that will be set when functions are called by external
|
||||
* libraries.
|
||||
*
|
||||
* Use the predicate `Connection::instance()` to get references to database connections (following PEP 249).
|
||||
*
|
||||
* Extend this class if the module implementing PEP 249 offers more direct ways to obtain
|
||||
* a connection than going through `connect`.
|
||||
*/
|
||||
abstract class InstanceSource extends DataFlow::Node { }
|
||||
|
||||
/** A call to the `connect` function of a module that implements PEP 249. */
|
||||
private class ConnectCall extends InstanceSource, DataFlow::CallCfgNode {
|
||||
ConnectCall() { this.getFunction() = connect() }
|
||||
}
|
||||
|
||||
/** Gets a reference to a database connection (following PEP 249). */
|
||||
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result instanceof InstanceSource
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to a database connection (following PEP 249). */
|
||||
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides models for database cursors (following PEP 249).
|
||||
*
|
||||
* These are returned by the `cursor` method on a database connection.
|
||||
* See https://www.python.org/dev/peps/pep-0249/#cursor.
|
||||
*/
|
||||
module Cursor {
|
||||
/**
|
||||
* A source of database cursors (following PEP 249), extend this class to model new instances.
|
||||
*
|
||||
* This can include instantiations of the class, return values from function
|
||||
* calls, or a special parameter that will be set when functions are called by external
|
||||
* libraries.
|
||||
*
|
||||
* Use the predicate `Cursor::instance()` to get references to database cursors (following PEP 249).
|
||||
*
|
||||
* Extend this class if the module implementing PEP 249 offers more direct ways to obtain
|
||||
* a connection than going through `connect`.
|
||||
*/
|
||||
abstract class InstanceSource extends DataFlow::LocalSourceNode { }
|
||||
|
||||
/** Gets a reference to a database cursor. */
|
||||
private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result instanceof InstanceSource
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to a database cursor. */
|
||||
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
|
||||
/** Gets a reference to the `cursor` method on a database connection. */
|
||||
private DataFlow::TypeTrackingNode methodRef(DataFlow::TypeTracker t) {
|
||||
t.startInAttr("cursor") and
|
||||
result = Connection::instance()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = methodRef(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `cursor` method on a database connection. */
|
||||
DataFlow::Node methodRef() { methodRef(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
|
||||
/** A call to the `cursor` method on a database connection */
|
||||
private class CursorCall extends InstanceSource, DataFlow::CallCfgNode {
|
||||
CursorCall() { this.getFunction() = methodRef() }
|
||||
}
|
||||
|
||||
/** Gets a reference to a result of calling the `cursor` method on a database connection. */
|
||||
private DataFlow::TypeTrackingNode methodResult(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result.asCfgNode().(CallNode).getFunction() = methodRef().asCfgNode()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = methodResult(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `Cursor::instance()` to get references to database cursors instead.
|
||||
*
|
||||
* Gets a reference to a result of calling the `cursor` method on a database connection.
|
||||
*/
|
||||
deprecated DataFlow::Node methodResult() {
|
||||
methodResult(DataFlow::TypeTracker::end()).flowsTo(result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the `execute` method on a cursor (or on a connection).
|
||||
*
|
||||
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
|
||||
* recognize it as an alias for constructing a cursor and calling `execute` on it.
|
||||
*
|
||||
* See https://www.python.org/dev/peps/pep-0249/#id15.
|
||||
*/
|
||||
private DataFlow::TypeTrackingNode execute(DataFlow::TypeTracker t) {
|
||||
t.startInAttr("execute") and
|
||||
result in [Cursor::instance(), Connection::instance()]
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = execute(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the `execute` method on a cursor (or on a connection).
|
||||
*
|
||||
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
|
||||
* recognize it as an alias for constructing a cursor and calling `execute` on it.
|
||||
*
|
||||
* See https://www.python.org/dev/peps/pep-0249/#id15.
|
||||
*/
|
||||
DataFlow::Node execute() { execute(DataFlow::TypeTracker::end()).flowsTo(result) }
|
||||
|
||||
/** A call to the `execute` method on a cursor (or on a connection). */
|
||||
private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode {
|
||||
ExecuteCall() { this.getFunction() = execute() }
|
||||
|
||||
override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import python
|
||||
import experimental.meta.ConceptsTest
|
||||
@@ -0,0 +1,3 @@
|
||||
argumentToEnsureNotTaintedNotMarkedAsSpurious
|
||||
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
|
||||
failures
|
||||
@@ -0,0 +1 @@
|
||||
import experimental.meta.InlineTaintTest
|
||||
@@ -0,0 +1,19 @@
|
||||
import peewee
|
||||
import playhouse.pool
|
||||
|
||||
# This is just one example of one of the support databases
|
||||
# see https://docs.peewee-orm.com/en/latest/peewee/database.html
|
||||
db = peewee.MySQLDatabase()
|
||||
|
||||
conn = db.connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("sql") # $ getSql="sql"
|
||||
|
||||
cursor = db.cursor()
|
||||
cursor.execute("sql") # $ getSql="sql"
|
||||
|
||||
db.execute_sql("sql") # $ getSql="sql"
|
||||
|
||||
# Pool extension
|
||||
pool = playhouse.pool.PooledMySQLDatabase(...)
|
||||
pool.execute_sql("sql") # $ getSql="sql"
|
||||
Reference in New Issue
Block a user