forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathModuleObject.qll
More file actions
306 lines (242 loc) · 8.58 KB
/
ModuleObject.qll
File metadata and controls
306 lines (242 loc) · 8.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
import python
private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.Base
private import semmle.python.types.ModuleKind
abstract class ModuleObject extends Object {
ModuleObject () {
exists(Module m | m.getEntryNode() = this)
or
this.asBuiltin().getClass() = theModuleType().asBuiltin()
}
/** Gets the scope corresponding to this module, if this is a Python module */
Module getModule() {
none()
}
/** Gets the source scope corresponding to this module, if this is a Python module */
Module getSourceModule() {
none()
}
Container getPath() {
none()
}
/** Gets the name of this scope */
abstract string getName();
override string toString() {
result = "Module " + this.getName()
}
/** Gets the named attribute of this module. Using attributeRefersTo() instead
* may provide better results for presentation.
* */
pragma [noinline]
abstract Object getAttribute(string name);
/** Gets the named attribute of this module.
* Synonym for `getAttribute(name)` */
pragma [inline]
final Object attr(string name) {
result = this.getAttribute(name)
}
/** Whether the named attribute of this module "refers-to" value, with a known origin.
*/
abstract predicate attributeRefersTo(string name, Object value, ControlFlowNode origin);
/** Whether the named attribute of this module "refers-to" value, with known class and a known origin.
*/
abstract predicate attributeRefersTo(string name, Object value, ClassObject cls, ControlFlowNode origin);
/** Gets the package for this module. */
PackageObject getPackage() {
this.getName().matches("%.%") and
result.getName() = this.getName().regexpReplaceAll("\\.[^.]*$", "")
}
/** Whether this module "exports" `name`. That is, whether using `import *` on this module
will result in `name` being added to the namespace. */
predicate exports(string name) {
PointsTo::module_exports(this, name)
}
/** Whether the complete set of names "exported" by this module can be accurately determined */
abstract predicate exportsComplete();
/** Gets the short name of the module. For example the short name of module x.y.z is 'z' */
string getShortName() {
result = this.getName().suffix(this.getPackage().getName().length()+1)
or
result = this.getName() and not exists(this.getPackage())
}
/** Whether this module is imported by 'import name'. For example on a linux system,
* the module 'posixpath' is imported as 'os.path' or as 'posixpath' */
predicate importedAs(string name) {
PointsTo::module_imported_as(this, name)
}
abstract predicate hasAttribute(string name);
ModuleObject getAnImportedModule() {
result.importedAs(this.getModule().getAnImportedModuleName())
}
/** Gets the kind for this module. Will be one of
* "module", "script" or "plugin".
*/
string getKind() {
result = getKindForModule(this)
}
override boolean booleanValue() {
result = true
}
}
class BuiltinModuleObject extends ModuleObject {
BuiltinModuleObject () {
this.asBuiltin().getClass() = theModuleType().asBuiltin()
}
override string getName() {
result = this.asBuiltin().getName()
}
override Object getAttribute(string name) {
result.asBuiltin() = this.asBuiltin().getMember(name)
}
override predicate hasAttribute(string name) {
exists(this.asBuiltin().getMember(name))
}
override predicate attributeRefersTo(string name, Object value, ControlFlowNode origin) {
none()
}
override predicate attributeRefersTo(string name, Object value, ClassObject cls, ControlFlowNode origin) {
none()
}
override predicate exportsComplete() {
any()
}
}
class PythonModuleObject extends ModuleObject {
PythonModuleObject() {
exists(Module m | m.getEntryNode() = this |
not m.isPackage()
)
}
override string getName() {
result = this.getModule().getName()
}
override Module getModule() {
result = this.getOrigin()
}
override Module getSourceModule() {
result = this.getOrigin()
}
override Container getPath() {
result = this.getModule().getFile()
}
override Object getAttribute(string name) {
this.attributeRefersTo(name, result, _, _)
}
override predicate exportsComplete() {
exists(Module m |
m = this.getModule() |
not exists(Call modify, Attribute attr, GlobalVariable all |
modify.getScope() = m and modify.getFunc() = attr and
all.getId() = "__all__" |
attr.getObject().(Name).uses(all)
)
)
}
override predicate hasAttribute(string name) {
PointsTo::module_defines_name(this.getModule(), name)
or
this.attributeRefersTo(name, _, _, _)
or
/* The interpreter always adds the __name__ and __package__ attributes */
name = "__name__" or name = "__package__"
}
override predicate attributeRefersTo(string name, Object value, ControlFlowNode origin) {
exists(CfgOrigin orig |
origin = orig.toCfgNode() and
PointsTo::py_module_attributes(this.getModule(), name, value, _, orig)
)
}
override predicate attributeRefersTo(string name, Object value, ClassObject cls, ControlFlowNode origin) {
exists(CfgOrigin orig |
origin = orig.toCfgNode() and
PointsTo::py_module_attributes(this.getModule(), name, value, cls, orig)
)
}
}
/** Primarily for internal use.
*
* Gets the object for the string text.
* The extractor will have populated a str object
* for each module name, with the name b'text' or u'text' (including the quotes).
*/
Object object_for_string(string text) {
result.asBuiltin().getClass() = theStrType().asBuiltin() and
exists(string repr |
repr = result.asBuiltin().getName() and
repr.charAt(1) = "'" |
/* Strip quotes off repr */
text = repr.substring(2, repr.length()-1)
)
}
class PackageObject extends ModuleObject {
PackageObject() {
exists(Module p | p.getEntryNode() = this |
p.isPackage()
)
}
override string getName() {
result = this.getModule().getName()
}
override Module getModule() {
result = this.getOrigin()
}
override Module getSourceModule() {
result = this.getModule().getInitModule()
}
override Container getPath() {
result = this.getModule().getPath()
}
ModuleObject submodule(string name) {
result.getPackage() = this and
name = result.getShortName()
}
override Object getAttribute(string name) {
PointsTo::package_attribute_points_to(this, name, result, _, _)
}
PythonModuleObject getInitModule() {
result.getModule() = this.getModule().getInitModule()
}
/** Holds if this package has no `__init__.py` file. */
predicate hasNoInitModule() {
not exists(Module m |
m.isPackageInit() and
m.getFile().getParent() = this.getPath()
)
}
override predicate exportsComplete() {
not exists(this.getInitModule())
or
this.getInitModule().exportsComplete()
}
override predicate hasAttribute(string name) {
exists(this.submodule(name))
or
this.getInitModule().hasAttribute(name)
}
override predicate attributeRefersTo(string name, Object value, ControlFlowNode origin) {
exists(CfgOrigin orig |
origin = orig.toCfgNode() and
PointsTo::package_attribute_points_to(this, name, value, _, orig)
)
}
override predicate attributeRefersTo(string name, Object value, ClassObject cls, ControlFlowNode origin) {
exists(CfgOrigin orig |
origin = orig.toCfgNode() and
PointsTo::package_attribute_points_to(this, name, value, cls, orig)
)
}
Location getLocation() {
none()
}
override predicate hasLocationInfo(string path, int bl, int bc, int el, int ec) {
path = this.getPath().getName() and
bl = 0 and bc = 0 and el = 0 and ec = 0
}
}
/** Utility module for predicates relevant to the `ModuleObject` class. */
module ModuleObject {
/** Gets a `ModuleObject` called `name`, if it exists. */
ModuleObject named(string name) {
result.getName() = name
}
}