Skip to content

Commit 50a75d2

Browse files
committed
Python: Fully module state of module using global variables and '$' pseudo-variable.
1 parent 4c0f123 commit 50a75d2

File tree

2 files changed

+42
-20
lines changed

2 files changed

+42
-20
lines changed

python/ql/src/semmle/python/pointsto/PointsTo.qll

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -114,19 +114,22 @@ module PointsTo {
114114
/** INTERNAL -- Do not use.
115115
*
116116
* Holds if `package.name` points to `(value, cls, origin)`, where `package` is a package object. */
117-
cached predicate package_attribute_points_to(PackageObject package, string name, Object value, ClassObject cls, ControlFlowNode origin) {
117+
cached predicate package_attribute_points_to(PackageObject package, string name, Object value, ClassObject cls, ObjectOrCfg origin) {
118118
py_module_attributes(package.getInitModule().getModule(), name, value, cls, origin)
119119
or
120120
exists(Module init |
121-
init = package.getInitModule().getModule() |
122-
not exists(PythonSsaSourceVariable v | v.getScope() = init | v.getName() = name or v.getName() = "$")
123-
or
124-
exists(EssaVariable v, PointsToContext imp |
125-
v.getScope() = init and v.getName() = "$" and v.getAUse() = init.getANormalExit() |
126-
SSA::ssa_variable_named_attribute_points_to(v, imp, name, undefinedVariable(), _, _) and
127-
imp.isImport()
121+
init = package.getInitModule().getModule() and
122+
not exists(EssaVariable var | var.getAUse() = init.getANormalExit() and var.getSourceVariable().getName() = name) and
123+
exists(EssaVariable var, Context context | var.getName() = "$" and
124+
context.isImport() and
125+
SSA::ssa_variable_named_attribute_points_to(var, context, name, undefinedVariable(), _, _) and
126+
origin = value and
127+
value = package.submodule(name) and
128+
cls = theModuleType()
128129
)
129-
) and explicitly_imported(value) and
130+
)
131+
or
132+
package.hasNoInitModule() and
130133
value = package.submodule(name) and cls = theModuleType() and origin = value
131134
}
132135

@@ -662,19 +665,25 @@ module PointsTo {
662665
/** Holds if `f` is a "from import" expression, `from mod import x` and points to `(value, cls, origin)`. */
663666
pragma [nomagic]
664667
private predicate from_import_points_to(ImportMemberNode f, PointsToContext context, Object value, ClassObject cls, ControlFlowNode origin) {
665-
exists(EssaVariable var, ObjectOrCfg orig |
666-
live_import_from_dot_in_init(f, var) and
667-
ssa_variable_points_to(var, context, value, cls, orig) and
668+
exists(string name, ModuleObject mod, ObjectOrCfg orig |
669+
points_to(f.getModule(name), context, mod, _, _) and
668670
origin = origin_from_object_or_here(orig, f)
669-
)
670-
or
671-
not live_import_from_dot_in_init(f, _) and
672-
exists(string name, ModuleObject mod |
673-
points_to(f.getModule(name), context, mod, _, _) |
674-
exists(ObjectOrCfg orig |
675-
Layer::module_attribute_points_to(mod, name, value, cls, orig) and
676-
origin = origin_from_object_or_here(orig, f)
671+
|
672+
mod.getSourceModule() = f.getEnclosingModule() and
673+
exists(EssaVariable var |
674+
var.getSourceVariable().getName() = name and var.getAUse() = f and
675+
ssa_variable_points_to(var, context, value, cls, orig)
677676
)
677+
or
678+
mod.getSourceModule() = f.getEnclosingModule() and
679+
not exists(EssaVariable var | var.getSourceVariable().getName() = name and var.getAUse() = f) and
680+
exists(EssaVariable dollar |
681+
dollar.getName() = "$" and dollar.getAUse() = f and
682+
SSA::ssa_variable_named_attribute_points_to(dollar, context, name, value, cls, orig)
683+
)
684+
or
685+
not mod.getSourceModule() = f.getEnclosingModule() and
686+
Layer::module_attribute_points_to(mod, name, value, cls, orig)
678687
)
679688
}
680689

python/ql/src/semmle/python/types/ModuleObject.qll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ abstract class ModuleObject extends Object {
1616
none()
1717
}
1818

19+
/** Gets the source scope corresponding to this module, if this is a Python module */
20+
Module getSourceModule() {
21+
none()
22+
}
23+
1924
Container getPath() {
2025
none()
2126
}
@@ -136,6 +141,10 @@ class PythonModuleObject extends ModuleObject {
136141
result = this.getOrigin()
137142
}
138143

144+
override Module getSourceModule() {
145+
result = this.getOrigin()
146+
}
147+
139148
override Container getPath() {
140149
result = this.getModule().getFile()
141150
}
@@ -206,6 +215,10 @@ class PackageObject extends ModuleObject {
206215
result = this.getOrigin()
207216
}
208217

218+
override Module getSourceModule() {
219+
result = this.getModule().getInitModule()
220+
}
221+
209222
override Container getPath() {
210223
exists(ModuleObject m |
211224
m.getPackage() = this |

0 commit comments

Comments
 (0)