@@ -7,9 +7,14 @@ private import python
77private import semmle.python.dataflow.new.DataFlow
88private import semmle.python.dataflow.new.TaintTracking
99private import semmle.python.ApiGraphs
10-
10+ private import semmle.python.Concepts
1111
1212private module SqlAlchemy {
13+ /**
14+ * An instantization of a SqlAlchemy Session object.
15+ * See https://docs.sqlalchemy.org/en/14/orm/session_api.html#sqlalchemy.orm.Session and
16+ * https://docs.sqlalchemy.org/en/14/orm/session_api.html#sqlalchemy.orm.sessionmaker
17+ */
1318 private class SqlAlchemySessionInstance extends API:: Node {
1419 SqlAlchemySessionInstance ( ) {
1520 this in [
@@ -18,26 +23,40 @@ private module SqlAlchemy {
1823 ]
1924 }
2025
21- override string toString ( ) { result = "Use of SqlAlchemy Session instance method " }
26+ override string toString ( ) { result = "Use of SqlAlchemy Session instantization " }
2227 }
2328
29+ /**
30+ * An instantization of a SqlAlchemy Engine object.
31+ * See https://docs.sqlalchemy.org/en/14/core/engines.html#sqlalchemy.create_engine
32+ */
2433 private class SqlAlchemyEngineInstance extends API:: Node {
2534 SqlAlchemyEngineInstance ( ) {
2635 this = API:: moduleImport ( "sqlalchemy" ) .getMember ( "create_engine" ) .getReturn ( )
2736 }
2837
29- override string toString ( ) { result = "Use of SqlAlchemy Engine instance method " }
38+ override string toString ( ) { result = "Use of SqlAlchemy create_engine member " }
3039 }
3140
41+ /**
42+ * An instantization of a SqlAlchemy Query object.
43+ * See https://docs.sqlalchemy.org/en/14/orm/query.html?highlight=query#sqlalchemy.orm.Query
44+ */
3245 private class SqlAlchemyQueryInstance extends API:: Node {
3346 SqlAlchemyQueryInstance ( ) {
34- this instanceof SqlAlchemySessionInstance and
35- this = this .getMember ( "query" ) .getReturn ( )
47+ this = any ( SqlAlchemySessionInstance sessionInstance ) .getMember ( "query" ) .getReturn ( )
3648 }
3749
38- override string toString ( ) { result = "Use of SqlAlchemy Query instance method " }
50+ override string toString ( ) { result = "Use of SqlAlchemy Session Query member " }
3951 }
4052
53+ /**
54+ * A call to `execute` meant to execute an SQL expression
55+ * See the following links:
56+ * - https://docs.sqlalchemy.org/en/14/core/connections.html?highlight=execute#sqlalchemy.engine.Connection.execute
57+ * - https://docs.sqlalchemy.org/en/14/core/connections.html?highlight=execute#sqlalchemy.engine.Engine.execute
58+ * - https://docs.sqlalchemy.org/en/14/orm/session_api.html?highlight=execute#sqlalchemy.orm.Session.execute
59+ */
4160 private class SqlAlchemyExecuteCall extends DataFlow:: CallCfgNode , SqlExecution:: Range {
4261 SqlAlchemyExecuteCall ( ) {
4362 exists ( SqlAlchemySessionInstance sessionInstance , SqlAlchemyEngineInstance engineInstance |
@@ -50,19 +69,27 @@ private module SqlAlchemy {
5069 override DataFlow:: Node getSql ( ) { result = this .getArg ( 0 ) }
5170 }
5271
72+ /**
73+ * A call to `scalar` meant to execute an SQL expression
74+ * See https://docs.sqlalchemy.org/en/14/orm/session_api.html#sqlalchemy.orm.Session.scalar and
75+ * https://docs.sqlalchemy.org/en/14/core/connections.html?highlight=scalar#sqlalchemy.engine.Engine.scalar
76+ */
5377 private class SqlAlchemyScalarCall extends DataFlow:: CallCfgNode , SqlExecution:: Range {
5478 SqlAlchemyScalarCall ( ) {
55- exists ( SqlAlchemySessionInstance sessionInstance |
56- this = sessionInstance .getMember ( "scalar" ) .getACall ( )
57- )
79+ this = any ( SqlAlchemySessionInstance sessionInstance ) .getMember ( "scalar" ) .getACall ( ) or
80+ this = any ( SqlAlchemyEngineInstance engineInstance ) .getMember ( "scalar" ) .getACall ( )
5881 }
5982
6083 override DataFlow:: Node getSql ( ) { result = this .getArg ( 0 ) }
6184 }
6285
86+ /**
87+ * A call on a Query object
88+ * See https://docs.sqlalchemy.org/en/14/orm/query.html?highlight=query#sqlalchemy.orm.Query
89+ */
6390 private class SqlAlchemyQueryCall extends DataFlow:: CallCfgNode , SqlExecution:: Range {
6491 SqlAlchemyQueryCall ( ) {
65- exists ( SqlAlchemyQueryInstance queryInstance | this = queryInstance .getAMember ( ) .getACall ( ) )
92+ this = any ( SqlAlchemyQueryInstance queryInstance ) .getAMember ( ) .getACall ( )
6693 }
6794
6895 override DataFlow:: Node getSql ( ) { result = this .getArg ( 0 ) }
0 commit comments