-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathProperties.qll
More file actions
109 lines (86 loc) · 3.76 KB
/
Properties.qll
File metadata and controls
109 lines (86 loc) · 3.76 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
import python
private import LegacyPointsTo
/**
* A Python property:
*
* @property def f():
* ....
*
* Also any instances of types.GetSetDescriptorType (which are equivalent, but implemented in C)
*/
abstract class PropertyObject extends Object {
PropertyObject() {
property_getter(this, _)
or
this.asBuiltin().getClass() = theBuiltinPropertyType().asBuiltin()
}
/** Gets the name of this property */
abstract string getName();
/** Gets the getter of this property */
abstract Object getGetter();
/** Gets the setter of this property */
abstract Object getSetter();
/** Gets the deleter of this property */
abstract Object getDeleter();
override string toString() { result = "Property " + this.getName() }
/** Whether this property is read-only. */
predicate isReadOnly() { not exists(this.getSetter()) }
/**
* Gets an inferred type of this property.
* That is the type returned by its getter function,
* not the type of the property object which is types.PropertyType.
*/
abstract ClassObject getInferredPropertyType();
}
class PythonPropertyObject extends PropertyObject {
PythonPropertyObject() { property_getter(this, _) }
override string getName() { result = this.getGetter().getName() }
/** Gets the getter function of this property */
override FunctionObject getGetter() { property_getter(this, result) }
override ClassObject getInferredPropertyType() {
result = this.getGetter().getAnInferredReturnType()
}
/** Gets the setter function of this property */
override FunctionObject getSetter() { property_setter(this, result) }
/** Gets the deleter function of this property */
override FunctionObject getDeleter() { property_deleter(this, result) }
}
class BuiltinPropertyObject extends PropertyObject {
BuiltinPropertyObject() { this.asBuiltin().getClass() = theBuiltinPropertyType().asBuiltin() }
override string getName() { result = this.asBuiltin().getName() }
/** Gets the getter method wrapper of this property */
override Object getGetter() { result.asBuiltin() = this.asBuiltin().getMember("__get__") }
override ClassObject getInferredPropertyType() { none() }
/** Gets the setter method wrapper of this property */
override Object getSetter() { result.asBuiltin() = this.asBuiltin().getMember("__set__") }
/** Gets the deleter method wrapper of this property */
override Object getDeleter() { result.asBuiltin() = this.asBuiltin().getMember("__delete__") }
}
private predicate property_getter(CallNode decorated, FunctionObject getter) {
decorated.getFunction().(ControlFlowNodeWithPointsTo).refersTo(thePropertyType()) and
decorated.getArg(0).(ControlFlowNodeWithPointsTo).refersTo(getter)
}
private predicate property_setter(CallNode decorated, FunctionObject setter) {
property_getter(decorated, _) and
exists(CallNode setter_call, AttrNode prop_setter |
prop_setter.getObject("setter").(ControlFlowNodeWithPointsTo).refersTo(decorated)
|
setter_call.getArg(0).(ControlFlowNodeWithPointsTo).refersTo(setter) and
setter_call.getFunction() = prop_setter
)
or
decorated.getFunction().(ControlFlowNodeWithPointsTo).refersTo(thePropertyType()) and
decorated.getArg(1).(ControlFlowNodeWithPointsTo).refersTo(setter)
}
private predicate property_deleter(CallNode decorated, FunctionObject deleter) {
property_getter(decorated, _) and
exists(CallNode deleter_call, AttrNode prop_deleter |
prop_deleter.getObject("deleter").(ControlFlowNodeWithPointsTo).refersTo(decorated)
|
deleter_call.getArg(0).(ControlFlowNodeWithPointsTo).refersTo(deleter) and
deleter_call.getFunction() = prop_deleter
)
or
decorated.getFunction().(ControlFlowNodeWithPointsTo).refersTo(thePropertyType()) and
decorated.getArg(2).(ControlFlowNodeWithPointsTo).refersTo(deleter)
}