mirror of
https://github.com/github/codeql.git
synced 2025-12-18 18:10:39 +01:00
Python: Refactor PEP249 to encapsulate in module
So global namespace doesn't contain `Connection` whenever `PEP249.qll` is imported
This commit is contained in:
@@ -8,7 +8,6 @@
|
|||||||
private import python
|
private import python
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.frameworks.PEP249
|
|
||||||
private import semmle.python.frameworks.ClickhouseDriver
|
private import semmle.python.frameworks.ClickhouseDriver
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ module ClickhouseDriver {
|
|||||||
* `clickhouse_driver` implements PEP249,
|
* `clickhouse_driver` implements PEP249,
|
||||||
* providing ways to execute SQL statements against a database.
|
* providing ways to execute SQL statements against a database.
|
||||||
*/
|
*/
|
||||||
class ClickHouseDriverPEP249 extends PEP249ModuleApiNode {
|
class ClickHouseDriverPEP249 extends PEP249::PEP249ModuleApiNode {
|
||||||
ClickHouseDriverPEP249() { this = API::moduleImport("clickhouse_driver") }
|
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.
|
* `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") }
|
DjangoDb() { this = API::moduleImport("django").getMember("db") }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ private module PrivateDjango {
|
|||||||
/** Gets a reference to the `django.db.connection` object. */
|
/** Gets a reference to the `django.db.connection` object. */
|
||||||
API::Node connection() { result = db().getMember("connection") }
|
API::Node connection() { result = db().getMember("connection") }
|
||||||
|
|
||||||
class DjangoDbConnection extends Connection::InstanceSource {
|
class DjangoDbConnection extends PEP249::Connection::InstanceSource {
|
||||||
DjangoDbConnection() { this = connection().getAUse() }
|
DjangoDbConnection() { this = connection().getAUse() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ private module MySQLdb {
|
|||||||
// MySQLdb
|
// MySQLdb
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** MySQLdb implements PEP 249, providing ways to execute SQL statements against a database. */
|
/** 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") }
|
MySQLdb() { this = API::moduleImport("MySQLdb") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ private module Mysql {
|
|||||||
* The mysql.connector module
|
* The mysql.connector module
|
||||||
* See https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html
|
* 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") }
|
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.dataflow.new.RemoteFlowSources
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
|
import semmle.python.frameworks.internal.PEP249Impl
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A module implementing PEP 249. Extend this class for implementations.
|
* 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 { }
|
abstract deprecated class PEP249Module extends DataFlow::Node { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract class encompassing API graph nodes that implement PEP 249.
|
* DEPRECATED: Use `PEP249::PEP249ModuleApiNode` instead.
|
||||||
* Extend this class for implementations.
|
|
||||||
*/
|
*/
|
||||||
abstract class PEP249ModuleApiNode extends API::Node {
|
deprecated class PEP249ModuleApiNode = PEP249::PEP249ModuleApiNode;
|
||||||
/** 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() }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides models for the `db.Connection` class
|
* DEPRECATED: Use `PEP249::Connection` instead.
|
||||||
*
|
|
||||||
* See https://www.python.org/dev/peps/pep-0249/#connection-objects.
|
|
||||||
*/
|
*/
|
||||||
module Connection {
|
deprecated module Connection = PEP249::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::LocalSourceNode 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) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides models for the `cursor` method on a connection.
|
* DEPRECATED: Use `PEP249::cursor` instead.
|
||||||
* See https://www.python.org/dev/peps/pep-0249/#cursor.
|
|
||||||
*/
|
*/
|
||||||
module cursor {
|
deprecated module cursor = PEP249::cursor;
|
||||||
/** Gets a reference to the `cursor` method on a connection. */
|
|
||||||
private DataFlow::LocalSourceNode 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::LocalSourceNode 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) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a reference to the `execute` method on a cursor (or on a connection).
|
* DEPRECATED: Use `PEP249::execute` instead.
|
||||||
*
|
|
||||||
* 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::LocalSourceNode execute(DataFlow::TypeTracker t) {
|
deprecated predicate execute = PEP249::execute/0;
|
||||||
t.startInAttr("execute") and
|
|
||||||
result in [cursor::methodResult(), 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).
|
* DEPRECATED: Use `PEP249::connect` instead.
|
||||||
*
|
|
||||||
* 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) }
|
deprecated predicate connect = PEP249::connect/0;
|
||||||
|
|
||||||
/** 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")] }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ private module Psycopg2 {
|
|||||||
// Psycopg
|
// Psycopg
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** psycopg2 implements PEP 249, providing ways to execute SQL statements against a database. */
|
/** 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") }
|
Psycopg2() { this = API::moduleImport("psycopg2") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ private import semmle.python.frameworks.PEP249
|
|||||||
*/
|
*/
|
||||||
private module PyMySQL {
|
private module PyMySQL {
|
||||||
/** PyMySQL implements PEP 249, providing ways to execute SQL statements against a database. */
|
/** 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") }
|
PyMySQLPEP249() { this = API::moduleImport("pymysql") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -885,7 +885,7 @@ private module Stdlib {
|
|||||||
*
|
*
|
||||||
* See https://devdocs.io/python~3.9/library/sqlite3
|
* See https://devdocs.io/python~3.9/library/sqlite3
|
||||||
*/
|
*/
|
||||||
class Sqlite3 extends PEP249ModuleApiNode {
|
class Sqlite3 extends PEP249::PEP249ModuleApiNode {
|
||||||
Sqlite3() { this = API::moduleImport("sqlite3") }
|
Sqlite3() { this = API::moduleImport("sqlite3") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
134
python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll
Normal file
134
python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* 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 PEP 249.
|
||||||
|
*/
|
||||||
|
module PEP249 {
|
||||||
|
/**
|
||||||
|
* An abstract class encompassing API graph nodes that implement PEP 249.
|
||||||
|
* Extend this class for implementations.
|
||||||
|
*/
|
||||||
|
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() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides models for the `db.Connection` class
|
||||||
|
*
|
||||||
|
* See https://www.python.org/dev/peps/pep-0249/#connection-objects.
|
||||||
|
*/
|
||||||
|
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::LocalSourceNode 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) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides models for the `cursor` method on a connection.
|
||||||
|
* See https://www.python.org/dev/peps/pep-0249/#cursor.
|
||||||
|
*/
|
||||||
|
module cursor {
|
||||||
|
/** Gets a reference to the `cursor` method on a connection. */
|
||||||
|
private DataFlow::LocalSourceNode 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::LocalSourceNode 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) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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::LocalSourceNode 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))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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")] }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user