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

Skip to content

Commit b10a7cd

Browse files
committed
Python points-to: Make behviour of instances more consistent.
1 parent 8f74f91 commit b10a7cd

1 file changed

Lines changed: 54 additions & 43 deletions

File tree

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

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,45 @@ private import semmle.python.pointsto.MRO
88
private import semmle.python.pointsto.PointsToContext
99
private import semmle.python.types.Builtins
1010

11-
class SpecificInstanceInternal extends TSpecificInstance, ObjectInternal {
11+
abstract class InstanceObject extends ObjectInternal {
12+
13+
pragma [nomagic]
14+
override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) {
15+
PointsToInternal::attributeRequired(this, name) and
16+
(
17+
exists(ObjectInternal cls_attr |
18+
this.getClass().(ClassObjectInternal).lookup(name, cls_attr, _)
19+
|
20+
/* If class attribute is not a descriptor, that usually means it is some sort of
21+
* default value and likely overridden by an instance attribute. In that case
22+
* use `unknown` to signal that an attribute exists but to avoid false positives
23+
* f using the default value.
24+
*/
25+
cls_attr.isDescriptor() = false and value = ObjectInternal::unknown() and origin = CfgOrigin::unknown()
26+
or
27+
cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this, value, origin)
28+
)
29+
or
30+
exists(EssaVariable self, PythonFunctionObjectInternal init, Context callee |
31+
this.initializer(init, callee) and
32+
self_variable_reaching_init_exit(self) and
33+
self.getScope() = init.getScope() and
34+
AttributePointsTo::variableAttributePointsTo(self, callee, name, value, origin)
35+
)
36+
)
37+
}
38+
39+
abstract predicate initializer(PythonFunctionObjectInternal init, Context callee);
40+
41+
}
42+
43+
private predicate self_variable_reaching_init_exit(EssaVariable self) {
44+
BaseFlow::reaches_exit(self) and
45+
self.getSourceVariable().(Variable).isSelf() and
46+
self.getScope().getName() = "__init__"
47+
}
48+
49+
class SpecificInstanceInternal extends TSpecificInstance, InstanceObject {
1250

1351
override string toString() {
1452
result = this.getOrigin().getNode().toString()
@@ -76,35 +114,6 @@ class SpecificInstanceInternal extends TSpecificInstance, ObjectInternal {
76114
none()
77115
}
78116

79-
pragma [nomagic]
80-
override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) {
81-
PointsToInternal::attributeRequired(this, name) and
82-
exists(ObjectInternal cls_attr, CfgOrigin attr_orig |
83-
this.getClass().(ClassObjectInternal).lookup(name, cls_attr, attr_orig)
84-
|
85-
/* If class attribute is not a descriptor, that usually means it is some sort of
86-
* default value and likely overridden by an instance attribute. In that case
87-
* use `unknown` to signal that an attribute exists but to avoid false positives
88-
* for due to using the default value.
89-
*/
90-
cls_attr.isDescriptor() = false and value = ObjectInternal::unknown() and origin = CfgOrigin::unknown()
91-
or
92-
cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this, value, origin)
93-
)
94-
or
95-
exists(EssaVariable self, PythonFunctionObjectInternal init, Context callee |
96-
BaseFlow::reaches_exit(self) and
97-
self.getSourceVariable().(Variable).isSelf() and
98-
self.getScope() = init.getScope() and
99-
exists(CallNode call, Context caller, ClassObjectInternal cls |
100-
this = TSpecificInstance(call, cls, caller) and
101-
callee.fromCall(this.getOrigin(), caller) and
102-
cls.lookup("__init__", init, _)
103-
) and
104-
AttributePointsTo::variableAttributePointsTo(self, callee, name, value, origin)
105-
)
106-
}
107-
108117
pragma [noinline] override predicate attributesUnknown() { any() }
109118

110119
override predicate subscriptUnknown() { any() }
@@ -128,10 +137,18 @@ class SpecificInstanceInternal extends TSpecificInstance, ObjectInternal {
128137
result = lengthFromClass(this.getClass())
129138
}
130139

140+
override predicate initializer(PythonFunctionObjectInternal init, Context callee) {
141+
exists(CallNode call, Context caller, ClassObjectInternal cls |
142+
this = TSpecificInstance(call, cls, caller) and
143+
callee.fromCall(this.getOrigin(), caller) and
144+
cls.lookup("__init__", init, _)
145+
)
146+
}
147+
131148
}
132149

133150

134-
class SelfInstanceInternal extends TSelfInstance, ObjectInternal {
151+
class SelfInstanceInternal extends TSelfInstance, InstanceObject {
135152

136153
override string toString() {
137154
result = "self instance of " + this.getClass().(ClassObjectInternal).getName()
@@ -201,17 +218,6 @@ class SelfInstanceInternal extends TSelfInstance, ObjectInternal {
201218
none()
202219
}
203220

204-
pragma [nomagic] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) {
205-
PointsToInternal::attributeRequired(this, name) and
206-
exists(ObjectInternal cls_attr, CfgOrigin attr_orig |
207-
this.getClass().(ClassObjectInternal).lookup(name, cls_attr, attr_orig)
208-
|
209-
cls_attr.isDescriptor() = false and value = cls_attr and origin = attr_orig
210-
or
211-
cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this, value, origin)
212-
)
213-
}
214-
215221
pragma [noinline] override predicate attributesUnknown() { any() }
216222

217223
override predicate subscriptUnknown() { any() }
@@ -234,6 +240,12 @@ class SelfInstanceInternal extends TSelfInstance, ObjectInternal {
234240
result = lengthFromClass(this.getClass())
235241
}
236242

243+
override predicate initializer(PythonFunctionObjectInternal init, Context callee) {
244+
callee.isRuntime() and
245+
init.getScope() != this.getParameter().getScope() and
246+
this.getClass().attribute("__init__", init, _)
247+
}
248+
237249
}
238250

239251
/** Represents a value that has a known class, but no other information */
@@ -245,7 +257,6 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal {
245257

246258
/** The boolean value of this object, if it has one */
247259
override boolean booleanValue() {
248-
//result = this.getClass().instancesBooleanValue()
249260
result = maybe()
250261
}
251262

0 commit comments

Comments
 (0)