Skip to content

Commit 921371d

Browse files
committed
Python: Modernise the cyclic import queries.
1 parent 7a57a3c commit 921371d

File tree

4 files changed

+25
-19
lines changed

4 files changed

+25
-19
lines changed

python/ql/src/Imports/Cyclic.qll

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,47 @@ predicate is_import_time(Stmt s) {
44
not s.getScope+() instanceof Function
55
}
66

7-
PythonModuleObject module_imported_by(PythonModuleObject m) {
7+
ModuleValue module_imported_by(ModuleValue m) {
88
exists(Stmt imp |
99
result = stmt_imports(imp) and
10-
imp.getEnclosingModule() = m.getModule() and
10+
imp.getEnclosingModule() = m.getScope() and
1111
// Import must reach exit to be part of a cycle
1212
imp.getAnEntryNode().getBasicBlock().reachesExit()
1313
)
1414
}
1515

1616
/** Is there a circular import of 'm1' beginning with 'm2'? */
17-
predicate circular_import(PythonModuleObject m1, PythonModuleObject m2) {
17+
predicate circular_import(ModuleValue m1, ModuleValue m2) {
1818
m1 != m2 and
1919
m2 = module_imported_by(m1) and m1 = module_imported_by+(m2)
2020
}
2121

22-
ModuleObject stmt_imports(ImportingStmt s) {
22+
ModuleValue stmt_imports(ImportingStmt s) {
2323
exists(string name |
2424
result.importedAs(name) and not name = "__main__" |
2525
name = s.getAnImportedModuleName()
2626
)
2727
}
2828

29-
predicate import_time_imported_module(PythonModuleObject m1, PythonModuleObject m2, Stmt imp) {
30-
imp.getEnclosingModule() = m1.getModule() and
29+
predicate import_time_imported_module(ModuleValue m1, ModuleValue m2, Stmt imp) {
30+
imp.getEnclosingModule() = m1.getScope() and
3131
is_import_time(imp) and
3232
m2 = stmt_imports(imp)
3333
}
3434

3535
/** Is there a cyclic import of 'm1' beginning with an import 'm2' at 'imp' where all the imports are top-level? */
36-
predicate import_time_circular_import(PythonModuleObject m1, PythonModuleObject m2, Stmt imp) {
36+
predicate import_time_circular_import(ModuleValue m1, ModuleValue m2, Stmt imp) {
3737
m1 != m2 and
38-
import_time_imported_module(m1, m2, imp) and
38+
import_time_imported_module(m1, m2, imp) and
3939
import_time_transitive_import(m2, _, m1)
4040
}
4141

42-
predicate import_time_transitive_import(PythonModuleObject base, Stmt imp, PythonModuleObject last) {
42+
predicate import_time_transitive_import(ModuleValue base, Stmt imp, ModuleValue last) {
4343
last != base and
4444
(
4545
import_time_imported_module(base, last, imp)
4646
or
47-
exists(PythonModuleObject mid |
47+
exists(ModuleValue mid |
4848
import_time_transitive_import(base, imp, mid) and
4949
import_time_imported_module(mid, last, _)
5050
)
@@ -56,11 +56,11 @@ predicate import_time_transitive_import(PythonModuleObject base, Stmt imp, Pytho
5656
/**
5757
* Returns import-time usages of module 'm' in module 'enclosing'
5858
*/
59-
predicate import_time_module_use(PythonModuleObject m, PythonModuleObject enclosing, Expr use, string attr) {
59+
predicate import_time_module_use(ModuleValue m, ModuleValue enclosing, Expr use, string attr) {
6060
exists(Expr mod |
61-
use.getEnclosingModule() = enclosing.getModule() and
61+
use.getEnclosingModule() = enclosing.getScope() and
6262
not use.getScope+() instanceof Function
63-
and mod.refersTo(m)
63+
and mod.pointsTo(m)
6464
|
6565
// either 'M.foo'
6666
use.(Attribute).getObject() = mod and use.(Attribute).getName() = attr
@@ -74,14 +74,14 @@ predicate import_time_module_use(PythonModuleObject m, PythonModuleObject enclos
7474
AttributeError at 'use' (in module 'other') caused by 'first.attr' not being defined as its definition can
7575
occur after the import 'other' in 'first'.
7676
*/
77-
predicate failing_import_due_to_cycle(PythonModuleObject first, PythonModuleObject other, Stmt imp,
77+
predicate failing_import_due_to_cycle(ModuleValue first, ModuleValue other, Stmt imp,
7878
ControlFlowNode defn, Expr use, string attr) {
7979
import_time_imported_module(other, first, _) and
8080
import_time_transitive_import(first, imp, other) and
8181
import_time_module_use(first, other, use, attr) and
82-
exists(ImportTimeScope n, SsaVariable v |
82+
exists(ImportTimeScope n, SsaVariable v |
8383
defn = v.getDefinition() and
84-
n = first.getModule() and v.getVariable().getScope() = n and v.getId() = attr |
84+
n = first.getScope() and v.getVariable().getScope() = n and v.getId() = attr |
8585
not defn.strictlyDominates(imp.getAnEntryNode())
8686
)
8787
and not exists(If i | i.isNameEqMain() and i.contains(use))

python/ql/src/Imports/CyclicImport.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
import python
1515
import Cyclic
1616

17-
from PythonModuleObject m1, PythonModuleObject m2, Stmt imp
17+
from ModuleValue m1, ModuleValue m2, Stmt imp
1818
where
19-
imp.getEnclosingModule() = m1.getModule()
19+
imp.getEnclosingModule() = m1.getScope()
2020
and stmt_imports(imp) = m2
2121
and circular_import(m1, m2)
2222
and m1 != m2

python/ql/src/Imports/ModuleLevelCyclicImport.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import Cyclic
2222
// then if we import the 'used' module, we will reach the cyclic import, start importing the 'using'
2323
// module, hit the 'use', and then crash due to the imported symbol not having been defined yet
2424

25-
from PythonModuleObject m1, Stmt imp, PythonModuleObject m2, string attr, Expr use, ControlFlowNode defn
25+
from ModuleValue m1, Stmt imp, ModuleValue m2, string attr, Expr use, ControlFlowNode defn
2626
where failing_import_due_to_cycle(m1, m2, imp, defn, use, attr)
2727
select use, "'" + attr + "' may not be defined if module $@ is imported before module $@, " +
2828
"as the $@ of " + attr + " occurs after the cyclic $@ of " + m2.getName() + ".",

python/ql/src/semmle/python/objects/ObjectAPI.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ class ModuleValue extends Value {
133133
result = this.(PythonModuleObjectInternal).getSourceModule().getFile()
134134
}
135135

136+
/** Whether this module is imported by 'import name'. For example on a linux system,
137+
* the module 'posixpath' is imported as 'os.path' or as 'posixpath' */
138+
predicate importedAs(string name) {
139+
PointsToInternal::module_imported_as(this, name)
140+
}
141+
136142
}
137143

138144
module Module {

0 commit comments

Comments
 (0)