Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dd83149

Browse files
committed
Python points-to: Port old API classes to use new points-to.
1 parent aa30745 commit dd83149

25 files changed

Lines changed: 632 additions & 3898 deletions

python/ql/src/python.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@ import semmle.dataflow.SSA
3636
import semmle.python.pointsto.Base
3737
import semmle.python.pointsto.Context
3838
import semmle.python.pointsto.CallGraph
39+
import semmle.python.objects.ObjectAPI
3940

4041
import site

python/ql/src/semmle/python/Exprs.qll

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import python
2-
private import semmle.python.pointsto.PointsTo
2+
private import semmle.python.pointsto.PointsTo2
33

44
/** An expression */
55
class Expr extends Expr_, AstNode {
@@ -78,37 +78,42 @@ class Expr extends Expr_, AstNode {
7878
* NOTE: For complex dataflow, involving multiple stages of points-to analysis, it may be more precise to use
7979
* `ControlFlowNode.refersTo(...)` instead.
8080
*/
81-
predicate refersTo(Object value, ClassObject cls, AstNode origin) {
82-
not py_special_objects(cls, "_semmle_unknown_type")
83-
and
84-
not value = unknownValue()
85-
and
86-
PointsTo::points_to(this.getAFlowNode(), _, value, cls, origin.getAFlowNode())
81+
predicate refersTo(Object obj, ClassObject cls, AstNode origin) {
82+
this.refersTo(_, obj, cls, origin)
8783
}
8884

8985
/** Gets what this expression might "refer-to" in the given `context`.
9086
*/
91-
predicate refersTo(Context context, Object value, ClassObject cls, AstNode origin) {
92-
not py_special_objects(cls, "_semmle_unknown_type")
93-
and
94-
PointsTo::points_to(this.getAFlowNode(), context, value, cls, origin.getAFlowNode())
87+
predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) {
88+
exists(Value value, ControlFlowNode cfgorigin |
89+
PointsTo2::points_to(this.getAFlowNode(), context, value, cfgorigin) and
90+
origin.getAFlowNode() = cfgorigin and
91+
cls = value.getClass().getSource() |
92+
if exists(value.getSource()) then
93+
obj = value.getSource()
94+
else
95+
obj = cfgorigin
96+
)
9597
}
9698

9799
/** Whether this expression might "refer-to" to `value` which is from `origin`
98100
* Unlike `this.refersTo(value, _, origin)`, this predicate includes results
99101
* where the class cannot be inferred.
100102
*/
101-
predicate refersTo(Object value, AstNode origin) {
102-
PointsTo::points_to(this.getAFlowNode(), _, value, _, origin.getAFlowNode())
103-
and
104-
not value = unknownValue()
103+
predicate refersTo(Object obj, AstNode origin) {
104+
exists(Value value, ControlFlowNode cfgorigin |
105+
PointsTo2::points_to(this.getAFlowNode(), _, value, cfgorigin) and
106+
origin.getAFlowNode() = cfgorigin and
107+
if exists(value.getSource()) then
108+
obj = value.getSource()
109+
else
110+
obj = cfgorigin
111+
)
105112
}
106113

107114
/** Equivalent to `this.refersTo(value, _)` */
108-
predicate refersTo(Object value) {
109-
PointsTo::points_to(this.getAFlowNode(), _, value, _, _)
110-
and
111-
not value = unknownValue()
115+
predicate refersTo(Object obj) {
116+
this.refersTo(obj, _)
112117
}
113118

114119
}

python/ql/src/semmle/python/Flow.qll

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import python
22
import semmle.python.flow.NameNode
3-
private import semmle.python.pointsto.PointsTo
3+
private import semmle.python.pointsto.PointsTo2
44

55

66
/* Note about matching parent and child nodes and CFG splitting:
@@ -212,47 +212,60 @@ class ControlFlowNode extends @py_flow_node {
212212
py_scope_flow(this, _, -1)
213213
}
214214

215-
/** Use ControlFlowNode.refersTo() instead. */
216-
deprecated Object pointsTo() {
217-
this.refersTo(result)
215+
/** The value that this ControlFlowNode points-to. */
216+
predicate pointsTo(Value value) {
217+
this.pointsTo(_, value, _)
218+
}
219+
220+
/** The value and origin that this ControlFlowNode points-to. */
221+
predicate pointsTo(Value value, ControlFlowNode origin) {
222+
this.pointsTo(_, value, origin)
223+
}
224+
225+
/** The value and origin that this ControlFlowNode points-to, given the context. */
226+
predicate pointsTo(Context context, Value value, ControlFlowNode origin) {
227+
PointsTo2::points_to(this, context, value, origin)
218228
}
219229

220230
/** Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to
221231
* analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly
222232
* precise, but may not provide information for a significant number of flow-nodes.
223233
* If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead.
224234
*/
225-
predicate refersTo(Object value, ClassObject cls, ControlFlowNode origin) {
226-
not py_special_objects(cls, "_semmle_unknown_type")
227-
and
228-
not value = unknownValue()
229-
and
230-
PointsTo::points_to(this, _, value, cls, origin)
235+
predicate refersTo(Object obj, ClassObject cls, ControlFlowNode origin) {
236+
this.refersTo(_, obj, cls, origin)
231237
}
232238

233239
/** Gets what this expression might "refer-to" in the given `context`.
234240
*/
235-
predicate refersTo(Context context, Object value, ClassObject cls, ControlFlowNode origin) {
236-
not py_special_objects(cls, "_semmle_unknown_type")
237-
and
238-
PointsTo::points_to(this, context, value, cls, origin)
241+
predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) {
242+
exists(Value value |
243+
PointsTo2::points_to(this, context, value, origin) and
244+
cls = value.getClass().getSource() |
245+
if exists(value.getSource().(Object)) then
246+
obj = value.getSource()
247+
else
248+
obj = origin
249+
)
239250
}
240251

241252
/** Whether this flow node might "refer-to" to `value` which is from `origin`
242253
* Unlike `this.refersTo(value, _, origin)` this predicate includes results
243254
* where the class cannot be inferred.
244255
*/
245-
predicate refersTo(Object value, ControlFlowNode origin) {
246-
PointsTo::points_to(this, _, value, _, origin)
247-
and
248-
not value = unknownValue()
256+
predicate refersTo(Object obj, ControlFlowNode origin) {
257+
exists(Value value |
258+
PointsTo2::points_to(this, _, value, origin) |
259+
if exists(value.getSource().(Object)) then
260+
obj = value.getSource()
261+
else
262+
obj = origin
263+
)
249264
}
250265

251266
/** Equivalent to `this.refersTo(value, _)` */
252-
predicate refersTo(Object value) {
253-
PointsTo::points_to(this, _, value, _, _)
254-
and
255-
not value = unknownValue()
267+
predicate refersTo(Object obj) {
268+
this.refersTo(obj, _)
256269
}
257270

258271
/** Gets the basic block containing this flow node */

python/ql/src/semmle/python/Import.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class Alias extends Alias_ {
1414
private predicate valid_module_name(string name) {
1515
exists(Module m | m.getName() = name)
1616
or
17-
exists(Builtin cmod | cmod.getClass() = theModuleType().asBuiltin() and cmod.getName() = name)
17+
exists(Builtin cmod | cmod.getClass() = Builtin::special("ModuleType") and cmod.getName() = name)
1818
}
1919

2020
/** An artificial expression representing an import */

python/ql/src/semmle/python/Module.qll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import python
2-
private import semmle.python.pointsto.PointsTo
2+
private import semmle.python.objects.ObjectAPI
3+
private import semmle.python.objects.Modules
34

45
/** A module. This is the top level element in an AST, corresponding to a source file.
56
* It is also a Scope; the scope of global variables. */
@@ -66,7 +67,10 @@ class Module extends Module_, Scope, AstNode {
6667
string getAnExport() {
6768
py_exports(this, result)
6869
or
69-
not PointsTo::module_defines_name(this, "__all__") and PointsTo::module_defines_name(this, result)
70+
exists(ModuleValue mod |
71+
mod.getSource() = this.getEntryNode() |
72+
not mod.exports(result)
73+
)
7074
}
7175

7276
/** Gets the source file for this module */

python/ql/src/semmle/python/SelfAttribute.qll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
*/
44

55
import python
6-
private import semmle.python.pointsto.PointsTo
76
private import semmle.python.pointsto.Filters
87

98
/** An attribute access where the left hand side of the attribute expression

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

Lines changed: 106 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import python
44
private import semmle.python.objects.TObject
55
private import semmle.python.objects.ObjectInternal
66
private import semmle.python.pointsto.PointsTo2
7-
private import semmle.python.pointsto.PointsToContext2
7+
private import semmle.python.pointsto.PointsToContext
88
private import semmle.python.pointsto.MRO2
99
private import semmle.python.types.Builtins
1010

@@ -54,7 +54,7 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
5454
result = this.getScope().toString()
5555
}
5656

57-
override predicate introduced(ControlFlowNode node, PointsToContext2 context) {
57+
override predicate introduced(ControlFlowNode node, PointsToContext context) {
5858
this = TPythonFunctionObject(node) and context.appliesTo(node)
5959
}
6060

@@ -72,7 +72,7 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
7272
this = TPythonFunctionObject(result)
7373
}
7474

75-
override predicate callResult(PointsToContext2 callee, ObjectInternal obj, CfgOrigin origin) {
75+
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
7676
exists(Function func, ControlFlowNode rval |
7777
func = this.getScope() and
7878
callee.appliesToScope(func) and
@@ -105,7 +105,7 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc
105105
result = "Builtin-function " + this.getBuiltin().getName()
106106
}
107107

108-
override predicate introduced(ControlFlowNode node, PointsToContext2 context) {
108+
override predicate introduced(ControlFlowNode node, PointsToContext context) {
109109
none()
110110
}
111111

@@ -115,7 +115,7 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc
115115

116116
override boolean isComparable() { result = true }
117117

118-
override predicate callResult(PointsToContext2 callee, ObjectInternal obj, CfgOrigin origin) {
118+
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
119119
none()
120120
}
121121

@@ -185,13 +185,13 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod
185185
result = TBuiltinClassObject(this.getBuiltin().getClass())
186186
}
187187

188-
override predicate introduced(ControlFlowNode node, PointsToContext2 context) {
188+
override predicate introduced(ControlFlowNode node, PointsToContext context) {
189189
none()
190190
}
191191

192192
override boolean isComparable() { result = true }
193193

194-
override predicate callResult(PointsToContext2 callee, ObjectInternal obj, CfgOrigin origin) {
194+
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
195195
none()
196196
}
197197

@@ -236,13 +236,13 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod {
236236
result = TBuiltinClassObject(Builtin::special("MethodType"))
237237
}
238238

239-
override predicate introduced(ControlFlowNode node, PointsToContext2 context) {
239+
override predicate introduced(ControlFlowNode node, PointsToContext context) {
240240
this = TBoundMethod(node, _, _, context)
241241
}
242242

243243
override boolean isComparable() { result = false }
244244

245-
override predicate callResult(PointsToContext2 callee, ObjectInternal obj, CfgOrigin origin) {
245+
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
246246
this.getFunction().callResult(callee, obj, origin)
247247
}
248248

@@ -264,6 +264,103 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod {
264264

265265
}
266266

267+
class ClassMethodObjectInternal extends ObjectInternal, TClassMethod {
268+
269+
override string toString() {
270+
result = "classmethod()"
271+
}
272+
273+
override boolean booleanValue() { result = true }
274+
275+
override predicate introduced(ControlFlowNode node, PointsToContext context) {
276+
exists(CallableObjectInternal function |
277+
this = TClassMethod(node, function) and
278+
class_method(node, function, context)
279+
)
280+
}
281+
282+
CallableObjectInternal getFunction() {
283+
this = TClassMethod(_, result)
284+
}
285+
286+
override ClassDecl getClassDeclaration() { none() }
287+
288+
override boolean isClass() { result = false }
289+
290+
override ObjectInternal getClass() { result = ObjectInternal::builtin("classmethod") }
291+
292+
override boolean isComparable() { none() }
293+
294+
override Builtin getBuiltin() { none() }
295+
296+
override ControlFlowNode getOrigin() { this = TClassMethod(result, _) }
297+
298+
override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() }
299+
300+
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() }
301+
302+
override int intValue() { none() }
303+
304+
override string strValue() { none() }
305+
306+
override predicate calleeAndOffset(Function scope, int paramOffset) {
307+
this.getFunction().calleeAndOffset(scope, paramOffset)
308+
}
309+
310+
override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() }
311+
312+
override predicate attributesUnknown() { none() }
313+
314+
}
315+
316+
class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod {
317+
318+
override string toString() {
319+
result = "staticmethod()"
320+
}
321+
322+
override boolean booleanValue() { result = true }
323+
324+
override predicate introduced(ControlFlowNode node, PointsToContext context) {
325+
exists(CallableObjectInternal function |
326+
this = TStaticMethod(node, function) and
327+
static_method(node, function, context)
328+
)
329+
}
330+
331+
CallableObjectInternal getFunction() {
332+
this = TStaticMethod(_, result)
333+
}
334+
335+
override ClassDecl getClassDeclaration() { none() }
336+
337+
override boolean isClass() { result = false }
338+
339+
override ObjectInternal getClass() { result = ObjectInternal::builtin("staticmethod") }
340+
341+
override boolean isComparable() { none() }
342+
343+
override Builtin getBuiltin() { none() }
344+
345+
override ControlFlowNode getOrigin() { this = TStaticMethod(result, _) }
346+
347+
override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() }
348+
349+
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() }
350+
351+
override int intValue() { none() }
352+
353+
override string strValue() { none() }
354+
355+
override predicate calleeAndOffset(Function scope, int paramOffset) {
356+
this.getFunction().calleeAndOffset(scope, paramOffset)
357+
}
358+
359+
override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() }
360+
361+
override predicate attributesUnknown() { none() }
362+
363+
}
267364

268365

269366

0 commit comments

Comments
 (0)