Python: drop legacy essa import from ImportResolution

`ImportResolution.qll` was the last new-dataflow file with a direct
`import semmle.python.essa.SsaDefinitions`, used only for the
`SsaSource::init_module_submodule_defn` helper. Inline the 5-line body
as a local private predicate. No functional change — the inlined
predicate is clause-for-clause equivalent (the `f = init.getEntryNode()`
join only constrained `package = init`, since `Scope.getEntryNode()` is
unique per scope; we now express that constraint directly).

All 70 dataflow + ApiGraphs library-tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
yoff
2026-05-26 13:10:00 +00:00
parent 4ce6131ca3
commit 091479cd6b

View File

@@ -11,7 +11,18 @@ private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.ImportStar
private import semmle.python.dataflow.new.TypeTracking
private import semmle.python.dataflow.new.internal.DataFlowPrivate
private import semmle.python.essa.SsaDefinitions
/**
* Holds if the name of `var` refers to a submodule of a package and `init` is
* the `__init__` module of that package. Locally inlined replacement for the
* legacy `SsaSource::init_module_submodule_defn` so that this module has no
* direct dependency on `semmle.python.essa.SsaDefinitions`.
*/
private predicate initModuleSubmoduleDefn(GlobalVariable var, Module init) {
init.isPackageInit() and
exists(init.getPackage().getSubModule(var.getId())) and
var.getScope() = init
}
/**
* Python modules and the way imports are resolved are... complicated. Here's a crash course in how
@@ -71,7 +82,9 @@ module ImportResolution {
* Holds if there is an ESSA step from `defFrom` to `defTo`, which should be allowed
* for import resolution.
*/
private predicate allowedEssaImportStep(SsaImpl::EssaDefinition defFrom, SsaImpl::EssaDefinition defTo) {
private predicate allowedEssaImportStep(
SsaImpl::EssaDefinition defFrom, SsaImpl::EssaDefinition defTo
) {
// to handle definitions guarded by if-then-else
defFrom = defTo.(SsaImpl::PhiFunction).getAnInput()
// Note: legacy ESSA refinement-step (e.g. for `foo.bar = X`) is
@@ -160,7 +173,9 @@ module ImportResolution {
*/
private predicate no_or_complicated_all(Module m) {
// No mention of `__all__` in the module
not exists(Cfg::DefinitionNode def | def.getScope() = m and def.(Cfg::NameNode).getId() = "__all__")
not exists(Cfg::DefinitionNode def |
def.getScope() = m and def.(Cfg::NameNode).getId() = "__all__"
)
or
// `__all__` is set to a non-sequence value
exists(Cfg::DefinitionNode def |
@@ -328,7 +343,7 @@ module ImportResolution {
// imported yet.
exists(string submodule, Module package, SsaImpl::EssaVariable var |
submodule = var.getName() and
SsaSource::init_module_submodule_defn(var.getSourceVariable().getVariable(), package.getEntryNode()) and
initModuleSubmoduleDefn(var.getSourceVariable().getVariable(), package) and
m = getModuleFromName(package.getPackageName() + "." + submodule) and
result.asCfgNode() = var.getDefinition().(SsaImpl::EssaNodeDefinition).getDefiningNode()
)