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

Skip to content

Commit 39b9723

Browse files
committed
Python: Add support for bound-methods.
1 parent bf692f4 commit 39b9723

14 files changed

Lines changed: 882 additions & 284 deletions

File tree

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
2+
import python
3+
4+
private import semmle.python.objects.TObject
5+
private import semmle.python.objects.ObjectInternal
6+
private import semmle.python.pointsto.PointsTo2
7+
private import semmle.python.pointsto.PointsToContext2
8+
private import semmle.python.pointsto.MRO2
9+
private import semmle.python.types.Builtins
10+
11+
12+
abstract class CallableObjectInternal extends ObjectInternal {
13+
14+
override int intValue() {
15+
none()
16+
}
17+
18+
override string strValue() {
19+
none()
20+
}
21+
22+
override predicate isClass() { none() }
23+
24+
override predicate notClass() { any() }
25+
26+
/** The boolean value of this object, if it has one */
27+
override boolean booleanValue() {
28+
result = true
29+
}
30+
31+
/** Holds if this object may be true or false when evaluated as a bool */
32+
override predicate maybe() { none() }
33+
34+
override ClassDecl getClassDeclaration() {
35+
none()
36+
}
37+
38+
abstract string getName();
39+
}
40+
41+
42+
class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFunctionObject {
43+
44+
Function getScope() {
45+
exists(CallableExpr expr |
46+
this = TPythonFunctionObject(expr.getAFlowNode()) and
47+
result = expr.getInnerScope()
48+
)
49+
}
50+
51+
override string toString() {
52+
result = this.getScope().toString()
53+
}
54+
55+
override predicate introduced(ControlFlowNode node, PointsToContext2 context) {
56+
this = TPythonFunctionObject(node) and context.appliesTo(node)
57+
}
58+
59+
override ObjectInternal getClass() {
60+
result = TBuiltinClassObject(Builtin::special("FunctionType"))
61+
}
62+
63+
override predicate isComparable() {
64+
any()
65+
}
66+
67+
override predicate notComparable() {
68+
none()
69+
}
70+
71+
override Builtin getBuiltin() {
72+
none()
73+
}
74+
75+
override ControlFlowNode getOrigin() {
76+
this = TPythonFunctionObject(result)
77+
}
78+
79+
override predicate callResult(PointsToContext2 callee, ObjectInternal obj, CfgOrigin origin) {
80+
exists(Function func, ControlFlowNode rval |
81+
func = this.getScope() and
82+
callee.appliesToScope(func) and
83+
rval = func.getAReturnValueFlowNode() and
84+
PointsTo2::points_to(rval, callee, obj, origin)
85+
)
86+
}
87+
88+
override predicate calleeAndOffset(Function scope, int paramOffset) {
89+
scope = this.getScope() and paramOffset = 0
90+
}
91+
92+
override string getName() {
93+
result = this.getScope().getName()
94+
}
95+
96+
}
97+
98+
class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunctionObject {
99+
100+
override Builtin getBuiltin() {
101+
this = TBuiltinFunctionObject(result)
102+
}
103+
104+
override string toString() {
105+
result = "builtin function " + this.getBuiltin().getName()
106+
}
107+
108+
override predicate introduced(ControlFlowNode node, PointsToContext2 context) {
109+
none()
110+
}
111+
112+
override ObjectInternal getClass() {
113+
result = TBuiltinClassObject(this.getBuiltin().getClass())
114+
}
115+
116+
override predicate isComparable() {
117+
any()
118+
}
119+
120+
override predicate notComparable() {
121+
none()
122+
}
123+
124+
override predicate callResult(PointsToContext2 callee, ObjectInternal obj, CfgOrigin origin) {
125+
// TO DO .. Result should be be a unknown value of a known class if the return type is known or just an unknown.
126+
none()
127+
}
128+
129+
override ControlFlowNode getOrigin() {
130+
none()
131+
}
132+
133+
override predicate calleeAndOffset(Function scope, int paramOffset) {
134+
none()
135+
}
136+
137+
override string getName() {
138+
result = this.getBuiltin().getName()
139+
}
140+
141+
}
142+
143+
144+
class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethodObject {
145+
146+
override Builtin getBuiltin() {
147+
this = TBuiltinMethodObject(result)
148+
}
149+
150+
override string toString() {
151+
result = "builtin method " + this.getBuiltin().getName()
152+
}
153+
154+
override ObjectInternal getClass() {
155+
result = TBuiltinClassObject(this.getBuiltin().getClass())
156+
}
157+
158+
override predicate introduced(ControlFlowNode node, PointsToContext2 context) {
159+
none()
160+
}
161+
162+
override predicate isComparable() {
163+
any()
164+
}
165+
166+
override predicate notComparable() {
167+
none()
168+
}
169+
170+
override predicate callResult(PointsToContext2 callee, ObjectInternal obj, CfgOrigin origin) {
171+
// TO DO .. Result should be be a unknown value of a known class if the return type is known or just an unknown.
172+
none()
173+
}
174+
175+
override ControlFlowNode getOrigin() {
176+
none()
177+
}
178+
179+
override predicate calleeAndOffset(Function scope, int paramOffset) {
180+
none()
181+
}
182+
183+
override string getName() {
184+
result = this.getBuiltin().getName()
185+
}
186+
187+
}
188+
189+
class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod {
190+
191+
override Builtin getBuiltin() {
192+
none()
193+
}
194+
195+
CallableObjectInternal getFunction() {
196+
this = TBoundMethod(_, _, result, _)
197+
}
198+
199+
ObjectInternal getSelf() {
200+
this = TBoundMethod(_, result, _, _)
201+
}
202+
203+
override string toString() {
204+
result = "bound method '" + this.getFunction().getName() + "' of " + this.getSelf().toString()
205+
}
206+
207+
override ObjectInternal getClass() {
208+
result = TBuiltinClassObject(Builtin::special("MethodType"))
209+
}
210+
211+
override predicate introduced(ControlFlowNode node, PointsToContext2 context) {
212+
this = TBoundMethod(node, _, _, context)
213+
}
214+
215+
override predicate isComparable() {
216+
none()
217+
}
218+
219+
override predicate notComparable() {
220+
any()
221+
}
222+
223+
override predicate callResult(PointsToContext2 callee, ObjectInternal obj, CfgOrigin origin) {
224+
this.getFunction().callResult(callee, obj, origin)
225+
}
226+
227+
override ControlFlowNode getOrigin() {
228+
this = TBoundMethod(result, _, _, _)
229+
}
230+
231+
override predicate calleeAndOffset(Function scope, int paramOffset) {
232+
this.getFunction().calleeAndOffset(scope, paramOffset-1)
233+
}
234+
235+
override string getName() {
236+
result = this.getFunction().getName()
237+
}
238+
239+
}
240+
241+
242+
243+

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ abstract class ClassObjectInternal extends ObjectInternal {
3535

3636
abstract predicate attribute(string name, ObjectInternal value, CfgOrigin origin);
3737

38+
boolean isSpecial() {
39+
result = Types::getMro(this).isSpecial()
40+
}
3841
}
3942

4043
class PythonClassObjectInternal extends ClassObjectInternal, TPythonClassObject {
@@ -148,3 +151,55 @@ class BuiltinClassObjectInternal extends ClassObjectInternal, TBuiltinClassObjec
148151
}
149152

150153
}
154+
155+
156+
class UnknownClassInternal extends ClassObjectInternal, TUnknownClass {
157+
158+
override string toString() {
159+
none()
160+
}
161+
162+
override ClassDecl getClassDeclaration() {
163+
result = Builtin::unknownType()
164+
}
165+
166+
override ObjectInternal getClass() {
167+
result = TUnknownClass()
168+
}
169+
170+
override predicate introduced(ControlFlowNode node, PointsToContext2 context) {
171+
none()
172+
}
173+
174+
override predicate isComparable() {
175+
none()
176+
}
177+
178+
override predicate notComparable() {
179+
any()
180+
}
181+
182+
override Builtin getBuiltin() {
183+
none()
184+
}
185+
186+
override predicate callResult(PointsToContext2 callee, ObjectInternal obj, CfgOrigin origin) {
187+
obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() and
188+
callee_for_object(callee, this)
189+
}
190+
191+
override ControlFlowNode getOrigin() {
192+
none()
193+
}
194+
195+
override predicate calleeAndOffset(Function scope, int paramOffset) {
196+
none()
197+
}
198+
199+
override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) {
200+
none()
201+
}
202+
203+
}
204+
205+

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ private import semmle.python.types.Builtins
1010
class InstanceInternal extends TInstance, ObjectInternal {
1111

1212
override string toString() {
13-
result = "instance of " + this.getClass().(ClassObjectInternal).getClassDeclaration().getName()
13+
result = "instance of " + this.getClass().(ClassObjectInternal).getName()
1414
}
1515

1616
/** The boolean value of this object, if it has one */

0 commit comments

Comments
 (0)