Skip to content

Commit 3b6c7d6

Browse files
authored
Merge pull request #582 from markshannon/python-faster-points-to-2
Python points-to: Improve performance of subclass test predicates on large DBs
2 parents 5c3ff8a + 9311229 commit 3b6c7d6

File tree

1 file changed

+34
-49
lines changed

1 file changed

+34
-49
lines changed

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

Lines changed: 34 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -780,31 +780,19 @@ module PointsTo {
780780
)
781781
)
782782
}
783-
/*
784-
pragma [noinline]
785-
private Object version_hex_compare(CompareNode cmp, PointsToContext context) {
786-
exists(ControlFlowNode lesser, ControlFlowNode greater, boolean strict |
787-
inequality(cmp, lesser, greater, strict) and
788-
exists(TupleObject tuple, int comp |
789-
points_to(lesser, context, tuple, _, _) and
790-
points_to(greater, context, theSysHexVersionNumber(), _, _) and
791-
comp = version_tuple_compare(tuple)
792-
or
793-
points_to(lesser, context, theSysHexVersionNumber(), _, _) and
794-
points_to(greater, context, tuple, _, _) and
795-
comp = version_hex_compare(tuple)*-1
796-
|
797-
comp = -1 and result = theTrueObject()
798-
or
799-
comp = 0 and strict = false and result = theTrueObject()
800-
or
801-
comp = 0 and strict = true and result = theFalseObject()
802-
or
803-
comp = 1 and result = theFalseObject()
804-
)
783+
784+
/** Holds if `cls` is an element of the tuple referred to by `f`.
785+
* Helper for relevant_subclass_relation
786+
*/
787+
private predicate element_of_points_to_tuple(ControlFlowNode f, PointsToContext context, ClassObject cls) {
788+
exists(TupleObject t |
789+
points_to(f, context, t, _, _) |
790+
cls = t.getBuiltinElement(_)
791+
or
792+
points_to(t.getSourceElement(_), _, cls, _, _)
805793
)
806794
}
807-
*/
795+
808796
private predicate compare_expr_points_to(CompareNode cmp, PointsToContext context, Object value, ClassObject cls, ControlFlowNode origin) {
809797
equality_expr_points_to(cmp, context, value, cls, origin)
810798
or
@@ -2046,18 +2034,14 @@ module PointsTo {
20462034
private boolean issubclass_test_evaluates_boolean(ControlFlowNode expr, ControlFlowNode use, PointsToContext context, Object val, ClassObject cls, ControlFlowNode origin) {
20472035
points_to(use, context, val, cls, origin) and
20482036
exists(ControlFlowNode clsNode |
2049-
BaseFilters::issubclass(expr, clsNode, use) |
2037+
BaseFilters::issubclass(expr, clsNode, use)
2038+
|
20502039
exists(ClassObject scls |
2051-
points_to(clsNode, context, scls, _, _) |
20522040
result = Types::is_improper_subclass_bool(val, scls)
2053-
)
2054-
or exists(TupleObject t, ClassObject scls |
2055-
points_to(clsNode, context, t, _, _) and
2056-
result = Types::is_improper_subclass_bool(val, scls) and result = true
20572041
|
2058-
scls = t.getBuiltinElement(_)
2042+
points_to(clsNode, context, scls, _, _)
20592043
or
2060-
points_to(t.getSourceElement(_), _, scls, _, _)
2044+
element_of_points_to_tuple(clsNode, context, scls) and result = true
20612045
)
20622046
or
20632047
val = unknownValue() and result = maybe()
@@ -2070,18 +2054,14 @@ module PointsTo {
20702054
private boolean isinstance_test_evaluates_boolean(ControlFlowNode expr, ControlFlowNode use, PointsToContext context, Object val, ClassObject cls, ControlFlowNode origin) {
20712055
points_to(use, context, val, cls, origin) and
20722056
exists(ControlFlowNode clsNode |
2073-
BaseFilters::isinstance(expr, clsNode, use) |
2057+
BaseFilters::isinstance(expr, clsNode, use)
2058+
|
20742059
exists(ClassObject scls |
2075-
points_to(clsNode, context, scls, _, _) |
20762060
result = Types::is_improper_subclass_bool(cls, scls)
2077-
)
2078-
or exists(TupleObject t, ClassObject scls |
2079-
points_to(clsNode, context, t, _, _) and
2080-
result = Types::is_improper_subclass_bool(cls, scls) and result = true
20812061
|
2082-
scls = t.getBuiltinElement(_)
2062+
points_to(clsNode, context, scls, _, _)
20832063
or
2084-
points_to(t.getSourceElement(_), _, scls, _, _)
2064+
element_of_points_to_tuple(clsNode, context, scls) and result = true
20852065
)
20862066
or
20872067
val = unknownValue() and result = maybe()
@@ -2458,18 +2438,12 @@ module PointsTo {
24582438
}
24592439

24602440
private predicate relevant_subclass_relation(ClassObject cls, ClassObject sup) {
2461-
exists(ControlFlowNode supnode, ControlFlowNode use |
2441+
exists(ControlFlowNode supnode |
24622442
points_to(supnode, _, sup, _, _)
2463-
or exists(TupleObject t |
2464-
points_to(supnode, _, t, _, _) |
2465-
sup = t.getBuiltinElement(_)
2466-
or
2467-
points_to(t.getSourceElement(_), _, sup, _, _)
2468-
)
2469-
|
2470-
BaseFilters::issubclass(_, supnode, use) and points_to(use, _, cls, _, _)
24712443
or
2472-
BaseFilters::isinstance(_, supnode, use) and points_to(use, _, _, cls, _)
2444+
element_of_points_to_tuple(supnode, _, sup)
2445+
|
2446+
subclass_test(supnode, cls)
24732447
)
24742448
or
24752449
exists(ClassObject sub |
@@ -2478,6 +2452,17 @@ module PointsTo {
24782452
)
24792453
}
24802454

2455+
/** Holds if there is a subclass test of `f` against class `cls`.
2456+
* Helper for relevant_subclass_relation.
2457+
*/
2458+
private predicate subclass_test(ControlFlowNode f, ClassObject cls) {
2459+
exists(ControlFlowNode use |
2460+
BaseFilters::issubclass(_, f, use) and points_to(use, _, cls, _, _)
2461+
or
2462+
BaseFilters::isinstance(_, f, use) and points_to(use, _, _, cls, _)
2463+
)
2464+
}
2465+
24812466
cached ClassList get_mro(ClassObject cls) {
24822467
result = new_style_mro(cls) and is_new_style_bool(cls) = true
24832468
or

0 commit comments

Comments
 (0)