mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Python: Use API graphs in PEP249 support
Because the replacement extension point now extends `API::Node`, I modified the `toString` method of the latter to have an empty body. The alternative would be to require everyone to provide a `toString` predicate for their extensions, but seeing as these will usually be pointing to already existing API graph nodes, this seems silly. (This may be the reason why the equivalent method in the JS libs has such an implementation.)
This commit is contained in:
@@ -157,7 +157,7 @@ module API {
|
||||
/**
|
||||
* Gets a textual representation of this element.
|
||||
*/
|
||||
abstract string toString();
|
||||
string toString() { none() }
|
||||
|
||||
/**
|
||||
* Gets a path of the given `length` from the root to this node.
|
||||
|
||||
@@ -78,8 +78,11 @@ private module Django {
|
||||
/** Gets a reference to the `django.db` module. */
|
||||
DataFlow::Node db() { result = django_attr("db") }
|
||||
|
||||
class DjangoDb extends PEP249Module {
|
||||
DjangoDb() { this = db() }
|
||||
/**
|
||||
* `django.db` implements PEP249, providing ways to execute SQL statements against a database.
|
||||
*/
|
||||
private class DjangoDb extends PEP249ModuleApiNode {
|
||||
DjangoDb() { this = API::moduleImport("django").getMember("db") }
|
||||
}
|
||||
|
||||
/** Provides models for the `django.db` module. */
|
||||
|
||||
@@ -9,6 +9,7 @@ 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
|
||||
private import PEP249
|
||||
|
||||
/**
|
||||
@@ -21,19 +22,8 @@ private module MySQLdb {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MySQLdb
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Gets a reference to the `MySQLdb` module. */
|
||||
private DataFlow::Node moduleMySQLdb(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = DataFlow::importNode("MySQLdb")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = moduleMySQLdb(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `MySQLdb` module. */
|
||||
DataFlow::Node moduleMySQLdb() { result = moduleMySQLdb(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** MySQLdb implements PEP 249, providing ways to execute SQL statements against a database. */
|
||||
class MySQLdb extends PEP249Module {
|
||||
MySQLdb() { this = moduleMySQLdb() }
|
||||
class MySQLdb extends PEP249ModuleApiNode {
|
||||
MySQLdb() { this = API::moduleImport("MySQLdb") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ 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
|
||||
private import PEP249
|
||||
|
||||
/**
|
||||
@@ -21,64 +22,14 @@ private module MysqlConnectorPython {
|
||||
// ---------------------------------------------------------------------------
|
||||
// mysql
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Gets a reference to the `mysql` module. */
|
||||
private DataFlow::Node mysql(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = DataFlow::importNode("mysql")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = mysql(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `mysql` module. */
|
||||
DataFlow::Node mysql() { result = mysql(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/**
|
||||
* Gets a reference to the attribute `attr_name` of the `mysql` module.
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node mysql_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["connector"] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("mysql" + "." + attr_name)
|
||||
or
|
||||
t.startInAttr(attr_name) and
|
||||
result = mysql()
|
||||
)
|
||||
or
|
||||
// Due to bad performance when using normal setup with `mysql_attr(t2, attr_name).track(t2, t)`
|
||||
// we have inlined that code and forced a join
|
||||
exists(DataFlow::TypeTracker t2 |
|
||||
exists(DataFlow::StepSummary summary |
|
||||
mysql_attr_first_join(t2, attr_name, result, summary) and
|
||||
t = t2.append(summary)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate mysql_attr_first_join(
|
||||
DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary
|
||||
) {
|
||||
DataFlow::StepSummary::step(mysql_attr(t2, attr_name), res, summary)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the attribute `attr_name` of the `mysql` module.
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node mysql_attr(string attr_name) {
|
||||
result = mysql_attr(DataFlow::TypeTracker::end(), attr_name)
|
||||
}
|
||||
|
||||
/** Provides models for the `mysql` module. */
|
||||
module mysql {
|
||||
/**
|
||||
* The mysql.connector module
|
||||
* See https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html
|
||||
*/
|
||||
class MysqlConnector extends PEP249Module {
|
||||
MysqlConnector() { this = mysql_attr("connector") }
|
||||
class MysqlConnector extends PEP249ModuleApiNode {
|
||||
MysqlConnector() { this = API::moduleImport("mysql").getMember("connector") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,23 @@ 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
|
||||
|
||||
/** A module implementing PEP 249. Extend this class for implementations. */
|
||||
abstract class PEP249Module extends DataFlow::Node { }
|
||||
/**
|
||||
* A module implementing PEP 249. Extend this class for implementations.
|
||||
*
|
||||
* DEPRECATED: Extend `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.
|
||||
*/
|
||||
abstract class PEP249ModuleApiNode extends API::Node { }
|
||||
|
||||
/** Gets a reference to a connect call. */
|
||||
private DataFlow::Node connect(DataFlow::TypeTracker t) {
|
||||
t.startInAttr("connect") and
|
||||
result instanceof PEP249Module
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = connect(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to a connect call. */
|
||||
DataFlow::Node connect() { result = connect(DataFlow::TypeTracker::end()) }
|
||||
DataFlow::Node connect() { result = any(PEP249ModuleApiNode a).getMember("connect").getAUse() }
|
||||
|
||||
/**
|
||||
* Provides models for the `db.Connection` class
|
||||
@@ -43,10 +46,8 @@ module Connection {
|
||||
abstract class InstanceSource extends DataFlow::Node { }
|
||||
|
||||
/** A direct instantiation of `db.Connection`. */
|
||||
private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode {
|
||||
override CallNode node;
|
||||
|
||||
ClassInstantiation() { node.getFunction() = connect().asCfgNode() }
|
||||
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
|
||||
ClassInstantiation() { this.getFunction() = connect() }
|
||||
}
|
||||
|
||||
/** Gets a reference to an instance of `db.Connection`. */
|
||||
@@ -115,10 +116,8 @@ private DataFlow::Node execute(DataFlow::TypeTracker t) {
|
||||
DataFlow::Node execute() { result = execute(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** A call to the `execute` method on a cursor (or on a connection). */
|
||||
private class ExecuteCall extends SqlExecution::Range, DataFlow::CfgNode {
|
||||
override CallNode node;
|
||||
|
||||
ExecuteCall() { node.getFunction() = execute().asCfgNode() }
|
||||
private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode {
|
||||
ExecuteCall() { this.getFunction() = execute() }
|
||||
|
||||
override DataFlow::Node getSql() {
|
||||
result.asCfgNode() in [node.getArg(0), node.getArgByName("sql")]
|
||||
|
||||
@@ -9,6 +9,7 @@ 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
|
||||
private import PEP249
|
||||
|
||||
/**
|
||||
@@ -21,19 +22,8 @@ private module Psycopg2 {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Psycopg
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Gets a reference to the `psycopg2` module. */
|
||||
private DataFlow::Node psycopg2(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = DataFlow::importNode("psycopg2")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = psycopg2(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `psycopg2` module. */
|
||||
DataFlow::Node psycopg2() { result = psycopg2(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** psycopg2 implements PEP 249, providing ways to execute SQL statements against a database. */
|
||||
class Psycopg2 extends PEP249Module {
|
||||
Psycopg2() { this = psycopg2() }
|
||||
class Psycopg2 extends PEP249ModuleApiNode {
|
||||
Psycopg2() { this = API::moduleImport("psycopg2") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ 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
|
||||
private import PEP249
|
||||
|
||||
/**
|
||||
@@ -14,19 +15,8 @@ private import PEP249
|
||||
* See https://pypi.org/project/PyMySQL/
|
||||
*/
|
||||
private module PyMySQL {
|
||||
/** Gets a reference to the `pymysql` module. */
|
||||
private DataFlow::Node pymysql(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = DataFlow::importNode("pymysql")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = pymysql(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `pymysql` module. */
|
||||
DataFlow::Node pymysql() { result = pymysql(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** PyMySQL implements PEP 249, providing ways to execute SQL statements against a database. */
|
||||
class PyMySQLPEP249 extends PEP249Module {
|
||||
PyMySQLPEP249() { this = pymysql() }
|
||||
class PyMySQLPEP249 extends PEP249ModuleApiNode {
|
||||
PyMySQLPEP249() { this = API::moduleImport("pymysql") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1523,24 +1523,13 @@ private module Stdlib {
|
||||
// ---------------------------------------------------------------------------
|
||||
// sqlite3
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Gets a reference to the `sqlite3` module. */
|
||||
private DataFlow::Node sqlite3(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = DataFlow::importNode("sqlite3")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = sqlite3(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a reference to the `sqlite3` module. */
|
||||
DataFlow::Node sqlite3() { result = sqlite3(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/**
|
||||
* sqlite3 implements PEP 249, providing ways to execute SQL statements against a database.
|
||||
*
|
||||
* See https://devdocs.io/python~3.9/library/sqlite3
|
||||
*/
|
||||
class Sqlite3 extends PEP249Module {
|
||||
Sqlite3() { this = sqlite3() }
|
||||
class Sqlite3 extends PEP249ModuleApiNode {
|
||||
Sqlite3() { this = API::moduleImport("sqlite3") }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user