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

Skip to content

Commit 54c27e1

Browse files
committed
Python points-to: Various minor performance tweaks.
1 parent 23ca403 commit 54c27e1

4 files changed

Lines changed: 92 additions & 55 deletions

File tree

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

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,11 @@ class SelfInstanceInternal extends TSelfInstance, ObjectInternal {
197197
override predicate descriptorGet(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() }
198198

199199
override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) {
200-
descriptor.isDescriptor() = true and
201-
this = instance and
202-
exists(AttrNode attr |
203-
PointsToInternal::pointsTo(attr.getObject(name), _, this, _) and
204-
this.getClass().attribute(name, descriptor, _)
205-
)
200+
exists(AttrNode attr, ClassObjectInternal cls |
201+
receiver_type(attr, name, this, cls) and
202+
cls_descriptor(cls, name, descriptor)
203+
) and
204+
instance = this
206205
}
207206

208207
}
@@ -288,17 +287,25 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal {
288287
override predicate descriptorGet(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() }
289288

290289
override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) {
291-
descriptor.isDescriptor() = true and
292-
this = instance and
293-
exists(AttrNode attr |
294-
PointsToInternal::pointsTo(attr.getObject(name), _, this, _) and
295-
this.getClass().attribute(name, descriptor, _)
296-
)
290+
exists(AttrNode attr, ClassObjectInternal cls |
291+
receiver_type(attr, name, this, cls) and
292+
cls_descriptor(cls, name, descriptor)
293+
) and
294+
instance = this
297295
}
298296

299297
}
300298

301299

300+
private predicate receiver_type(AttrNode attr, string name, ObjectInternal value, ClassObjectInternal cls) {
301+
PointsToInternal::pointsTo(attr.getObject(name), _, value, _) and value.getClass() = cls
302+
}
303+
304+
private predicate cls_descriptor(ClassObjectInternal cls, string name, ObjectInternal descriptor) {
305+
cls.attribute(name, descriptor, _) and
306+
descriptor.isDescriptor() = true
307+
}
308+
302309
class SuperInstance extends TSuperInstance, ObjectInternal {
303310

304311
override string toString() {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ abstract class SequenceObjectInternal extends ObjectInternal {
3636
abstract class TupleObjectInternal extends SequenceObjectInternal {
3737

3838
override string toString() {
39-
result = "tuple()"
39+
result = "Tuple"
4040
}
4141

4242
/** Gets the class declaration for this object, if it is a declared class. */

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

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -149,27 +149,43 @@ predicate literal_instantiation(ControlFlowNode n, ClassObjectInternal cls, Poin
149149
}
150150

151151
predicate super_instantiation(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) {
152+
super_2args(instantiation, self, startclass, context)
153+
or
154+
super_noargs(instantiation, self, startclass, context)
155+
}
156+
157+
pragma [noinline]
158+
private predicate super_2args(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) {
159+
exists(ControlFlowNode func, ControlFlowNode arg0, ControlFlowNode arg1 |
160+
call2(instantiation, func, arg0, arg1) and
161+
PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("super"), _) and
162+
PointsToInternal::pointsTo(arg0, context, startclass, _) and
163+
PointsToInternal::pointsTo(arg1, context, self, _)
164+
)
165+
}
166+
167+
pragma [noinline]
168+
private predicate super_noargs(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) {
152169
PointsToInternal::pointsTo(instantiation.getFunction(), context, ObjectInternal::builtin("super"), _) and
153-
(
154-
PointsToInternal::pointsTo(instantiation.getArg(0), context, startclass, _) and
155-
PointsToInternal::pointsTo(instantiation.getArg(1), context, self, _)
156-
or
157-
major_version() = 3 and
158-
not exists(instantiation.getArg(0)) and
159-
exists(Function func |
160-
instantiation.getScope() = func and
161-
/* Implicit class argument is lexically enclosing scope */
162-
func.getScope() = startclass.(PythonClassObjectInternal).getScope() and
163-
/* Implicit 'self' is the 0th parameter */
164-
PointsToInternal::pointsTo(func.getArg(0).asName().getAFlowNode(), context, self, _)
165-
)
170+
not exists(instantiation.getArg(0)) and
171+
exists(Function func |
172+
instantiation.getScope() = func and
173+
/* Implicit class argument is lexically enclosing scope */
174+
func.getScope() = startclass.(PythonClassObjectInternal).getScope() and
175+
/* Implicit 'self' is the 0th parameter */
176+
PointsToInternal::pointsTo(func.getArg(0).asName().getAFlowNode(), context, self, _)
166177
)
167178
}
168179

180+
predicate call2(CallNode call, ControlFlowNode func, ControlFlowNode arg0, ControlFlowNode arg1) {
181+
not exists(call.getArg(2)) and
182+
func = call.getFunction() and
183+
arg0 = call.getArg(0) and
184+
arg1 = call.getArg(1)
185+
}
169186

170187
bindingset[self, function]
171188
predicate method_binding(AttrNode instantiation, ObjectInternal self, CallableObjectInternal function, PointsToContext context) {
172-
173189
exists(ObjectInternal obj, string name |
174190
receiver(instantiation, context, obj, name) |
175191
exists(ObjectInternal cls |

python/ql/src/semmle/python/pointsto/PointsTo.qll

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -423,10 +423,11 @@ cached module PointsToInternal {
423423

424424
/** Holds if ESSA edge refinement, `def`, refers to `(value, cls, origin)`. */
425425
private predicate ssa_filter_definition_points_to(PyEdgeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) {
426-
def.getSense() = Conditionals::testEvaluates(def.getTest(), def.getInput().getASourceUse(), context, value, origin)
427-
//exists(ControlFlowNode test, ControlFlowNode use |
428-
// refinement_test(test, use, Conditionals::branchEvaluatesTo(test, use, context, value, origin.toCfgNode()), def)
429-
//)
426+
def.getSense() = ssa_filter_definition_bool(def, context, value, origin)
427+
}
428+
429+
private boolean ssa_filter_definition_bool(PyEdgeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) {
430+
result = Conditionals::testEvaluates(def.getTest(), def.getInput().getASourceUse(), context, value, origin)
430431
}
431432

432433
/** Holds if ESSA definition, `uniphi`, refers to `(value, origin)`. */
@@ -982,6 +983,7 @@ module Conditionals {
982983
result = evaluates(expr, use, context, value, origin).booleanValue()
983984
}
984985

986+
pragma [noinline]
985987
ObjectInternal evaluates(ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal val, ControlFlowNode origin) {
986988
PointsToInternal::pointsTo(use, context, val, origin) and
987989
pinode_test(_, use) and expr = use and result = val
@@ -1111,19 +1113,21 @@ module Conditionals {
11111113
}
11121114

11131115
//private
1114-
predicate isinstance_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, ObjectInternal cls, ControlFlowNode origin) {
1116+
predicate isinstance_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, ObjectInternal cls) {
11151117
pinode_test_part(call, use) and
1116-
PointsToInternal::pointsTo(call.getFunction(), context, ObjectInternal::builtin("isinstance"), _) and
1117-
use = call.getArg(0) and
1118-
PointsToInternal::pointsTo(use, context, val, origin) and
1119-
PointsToInternal::pointsTo(call.getArg(1), context, cls, _)
1118+
exists(ControlFlowNode func, ControlFlowNode arg1 |
1119+
call2(call, func, use, arg1) and
1120+
PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("isinstance"), _) and
1121+
PointsToInternal::pointsTo(use, context, val, _) and
1122+
PointsToInternal::pointsTo(arg1, context, cls, _)
1123+
)
11201124
}
11211125

11221126
pragma [nomagic]
11231127
//private
11241128
boolean isinstance_test_evaluates_boolean(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val) {
11251129
exists(ObjectInternal cls |
1126-
isinstance_call(call, use, context, val, cls, _) |
1130+
isinstance_call(call, use, context, val, cls) |
11271131
result = Types::improperSubclass(val.getClass(), cls)
11281132
or
11291133
val = ObjectInternal::unknown() and result = maybe()
@@ -1134,18 +1138,20 @@ module Conditionals {
11341138
)
11351139
}
11361140

1137-
private predicate issubclass_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, ObjectInternal cls, ControlFlowNode origin) {
1138-
PointsToInternal::pointsTo(call.getFunction(), context, ObjectInternal::builtin("issubclass"), _) and
1139-
use = call.getArg(0) and
1140-
PointsToInternal::pointsTo(use, context, val, origin) and
1141-
PointsToInternal::pointsTo(call.getArg(1), context, cls, _)
1141+
private predicate issubclass_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, ObjectInternal cls) {
1142+
pinode_test_part(call, use) and
1143+
exists(ControlFlowNode func, ControlFlowNode arg1 |
1144+
call2(call, func, use, arg1) and
1145+
PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("issubclass"), _) and
1146+
PointsToInternal::pointsTo(use, context, val, _) and
1147+
PointsToInternal::pointsTo(arg1, context, cls, _)
1148+
)
11421149
}
11431150

11441151
pragma [nomagic]
11451152
private boolean issubclass_test_evaluates_boolean(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val) {
1146-
pinode_test_part(call, use) and
11471153
exists(ObjectInternal cls |
1148-
issubclass_call(call, use, context, val, cls, _) |
1154+
issubclass_call(call, use, context, val, cls) |
11491155
result = Types::improperSubclass(val, cls)
11501156
or
11511157
val = ObjectInternal::unknownClass() and result = maybe()
@@ -1161,14 +1167,17 @@ module Conditionals {
11611167
predicate requireSubClass(ObjectInternal sub, ObjectInternal sup) {
11621168
sup != ObjectInternal::unknownClass() and
11631169
sub != ObjectInternal::unknownClass() and
1164-
(sup.isClass() = true or sup instanceof TupleObjectInternal) and
1165-
(
1166-
issubclass_call(_, _, _, sub, sup, _) and sub.isClass() = true
1170+
exists(ObjectInternal sup_or_tuple |
1171+
issubclass_call(_, _, _, sub, sup_or_tuple) and sub.isClass() = true
11671172
or
11681173
exists(ObjectInternal val |
1169-
isinstance_call(_, _, _, val, sup, _) and
1174+
isinstance_call(_, _, _, val, sup_or_tuple) and
11701175
sub = val.getClass()
11711176
)
1177+
|
1178+
sup = sup_or_tuple
1179+
or
1180+
sup = sup_or_tuple.(TupleObjectInternal).getItem(_)
11721181
)
11731182
}
11741183

@@ -1181,7 +1190,7 @@ module Conditionals {
11811190
hasattr_call(_, _, _, val, name)
11821191
)
11831192
}
1184-
1193+
11851194
pragma [noinline]
11861195
private boolean inequalityEvaluatesBoolean(ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal val) {
11871196
pinode_test_part(expr, use) and
@@ -1462,16 +1471,21 @@ cached module Types {
14621471
cached boolean improperSubclass(ObjectInternal sub, ObjectInternal sup) {
14631472
sub = sup and result = true
14641473
or
1465-
result = mroContains(Types::getMro(sub), sup)
1466-
// TO DO...
1467-
// Handle tuples of classes
1474+
result = mroContains(Types::getMro(sub), sup, 0)
1475+
or
1476+
result = tupleSubclass(sub, sup, 0)
14681477
}
14691478

1470-
private boolean mroContains(ClassList mro, ObjectInternal sup) {
1471-
result = mroContains(mro, sup, 0)
1479+
private boolean tupleSubclass(ObjectInternal cls, TupleObjectInternal tpl, int n) {
1480+
Conditionals::requireSubClass(cls, tpl) and
1481+
(
1482+
n = tpl.length() and result = false
1483+
or
1484+
result = improperSubclass(cls, tpl.getItem(n)).booleanOr(tupleSubclass(cls, tpl, n+1))
1485+
)
14721486
}
14731487

1474-
private boolean mroContains(ClassList mro, ObjectInternal sup, int n) {
1488+
private boolean mroContains(ClassList mro, ClassObjectInternal sup, int n) {
14751489
exists(ClassObjectInternal cls |
14761490
Conditionals::requireSubClass(cls, sup) and
14771491
mro = getMro(cls)

0 commit comments

Comments
 (0)