mirror of
https://github.com/github/codeql.git
synced 2026-05-14 19:29:28 +02:00
Python: Port ModuleImportsItself.ql
Uses the existing machinery in ImportResolution.qll, after adding a few convenience predicates. The new modelling actually manages to find a result that the old points-to analysis did not. Apart from that there are no test changes.
This commit is contained in:
@@ -377,4 +377,30 @@ module ImportResolution {
|
||||
}
|
||||
|
||||
Module getModule(DataFlow::CfgNode node) { node = getModuleReference(result) }
|
||||
|
||||
/** Holds if module `importer` directly imports module `imported`. */
|
||||
predicate imports(Module importer, Module imported) {
|
||||
getImmediateModuleReference(imported).getScope() = importer
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the import statement `i` causes module `imported` to be imported.
|
||||
* For `from pkg import submodule`, both `pkg` and `pkg.submodule` are considered imported.
|
||||
*/
|
||||
predicate importedBy(ImportingStmt i, Module imported) {
|
||||
exists(Alias a | a = i.(Import).getAName() |
|
||||
getImmediateModuleReference(imported).asExpr() = a.getAsname()
|
||||
)
|
||||
or
|
||||
exists(ImportMember im | im = i.(Import).getAName().getValue() |
|
||||
getImmediateModuleReference(imported).asExpr() = im.getModule()
|
||||
)
|
||||
or
|
||||
getImmediateModuleReference(imported).asExpr() = i.(ImportStar).getModule().(ImportExpr)
|
||||
}
|
||||
|
||||
/** Gets a user-friendly name for module `m`, using the package name for `__init__` modules. */
|
||||
string moduleName(Module m) {
|
||||
if m.isPackageInit() then result = m.getPackageName() else result = m.getName()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,19 +12,19 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.internal.ImportResolution
|
||||
|
||||
predicate modules_imports_itself(ImportingStmt i, ModuleValue m) {
|
||||
i.getEnclosingModule() = m.getScope() and
|
||||
m =
|
||||
max(string s, ModuleValue m_ |
|
||||
s = i.getAnImportedModuleName() and
|
||||
m_.importedAs(s)
|
||||
|
|
||||
m_ order by s.length()
|
||||
)
|
||||
predicate modules_imports_itself(ImportingStmt i, Module m) {
|
||||
m = i.getEnclosingModule() and
|
||||
ImportResolution::importedBy(i, m) and
|
||||
// Exclude `from m import submodule` where the imported member is a submodule of m
|
||||
not exists(ImportMember im | im = i.(Import).getAName().getValue() |
|
||||
ImportResolution::getImmediateModuleReference(m).asExpr() = im.getModule() and
|
||||
ImportResolution::importedBy(i, any(Module sub | sub != m))
|
||||
)
|
||||
}
|
||||
|
||||
from ImportingStmt i, ModuleValue m
|
||||
from ImportingStmt i, Module m
|
||||
where modules_imports_itself(i, m)
|
||||
select i, "The module '" + m.getName() + "' imports itself."
|
||||
select i, "The module '" + ImportResolution::moduleName(m) + "' imports itself."
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
| imports_test.py:8:1:8:19 | Import | The module 'imports_test' imports itself. |
|
||||
| pkg_notok/__init__.py:4:1:4:16 | Import | The module 'pkg_notok' imports itself. |
|
||||
| pkg_notok/__init__.py:10:1:10:20 | Import | The module 'pkg_notok' imports itself. |
|
||||
| pkg_notok/__init__.py:12:1:12:25 | Import | The module 'pkg_notok' imports itself. |
|
||||
| pkg_notok/__init__.py:13:1:13:37 | Import | The module 'pkg_notok' imports itself. |
|
||||
| pkg_notok/__init__.py:14:1:14:23 | from pkg_notok import * | The module 'pkg_notok' imports itself. |
|
||||
|
||||
Reference in New Issue
Block a user