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

Skip to content

Commit a03e101

Browse files
committed
Python points-to: Improve performance.
1 parent 972ac0f commit a03e101

2 files changed

Lines changed: 67 additions & 62 deletions

File tree

python/ql/src/semmle/python/Flow.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,18 @@ class BasicBlock extends @py_flow_node {
10141014
result = this.getLastNode().getAFalseSuccessor().getBasicBlock()
10151015
}
10161016

1017+
/** Gets an exceptional successor to this basic block */
1018+
BasicBlock getAnUnconditionalSuccessor() {
1019+
result = this.getASuccessor() and
1020+
not result = this.getATrueSuccessor() and
1021+
not result = this.getAFalseSuccessor()
1022+
}
1023+
1024+
/** Gets an exceptional successor to this basic block */
1025+
BasicBlock getAnExceptionalSuccessor() {
1026+
result = this.getLastNode().getAnExceptionalSuccessor().getBasicBlock()
1027+
}
1028+
10171029
/** Gets the scope of this block */
10181030
pragma [nomagic] Scope getScope() {
10191031
exists(ControlFlowNode n |

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

Lines changed: 55 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -214,43 +214,28 @@ cached module PointsToInternal {
214214

215215
/* Holds if BasicBlock `b` is reachable, given the context `context`. */
216216
cached predicate reachableBlock(BasicBlock b, PointsToContext context) {
217-
context.appliesToScope(b.getScope()) and not exists(ConditionBlock guard | guard.controls(b, _))
218-
or
219-
exists(ConditionBlock guard |
220-
guard = b.getImmediatelyControllingBlock() and
221-
reachableBlock(guard, context)
222-
|
223-
allowsFlow(guard, b, context)
224-
or
225-
/* Assume the true edge of an assert is reachable (except for assert 0/False) */
226-
guard.controls(b, true) and
227-
exists(Assert a, Expr test |
228-
a.getTest() = test and
229-
guard.getLastNode().getNode() = test and
230-
not test instanceof ImmutableLiteral
231-
)
232-
)
233-
}
234-
235-
pragma [noopt]
236-
private predicate allowsFlow(ConditionBlock guard, BasicBlock b, PointsToContext context) {
237-
exists(ObjectInternal value, boolean sense, ControlFlowNode test |
238-
test = guard.getLastNode() and
239-
pointsTo(test, context, value, _) and
240-
sense = value.booleanValue() and
241-
guard.controls(b, sense)
217+
exists(Scope scope |
218+
context.appliesToScope(scope) and
219+
scope.getEntryNode().getBasicBlock() = b
242220
)
221+
or
222+
reachableEdge(_, b, context)
243223
}
244224

245-
/* Holds if the edge `pred` -> `succ` is reachable, given the context `context`.
246-
*/
247-
pragma [noopt]
248-
cached predicate controlledReachableEdge(BasicBlock pred, BasicBlock succ, PointsToContext context) {
249-
exists(ConditionBlock guard, ObjectInternal value, boolean sense, ControlFlowNode test |
250-
test = guard.getLastNode() and
251-
pointsTo(test, context, value, _) and
252-
sense = value.booleanValue() and
253-
guard.controlsEdge(pred, succ, sense)
225+
private predicate reachableEdge(BasicBlock pred, BasicBlock succ, PointsToContext context) {
226+
reachableBlock(pred, context) and
227+
(
228+
pred.getAnUnconditionalSuccessor() = succ
229+
or
230+
exists(ObjectInternal value, boolean sense, ControlFlowNode test |
231+
test = pred.getLastNode() and
232+
pointsTo(test, context, value, _) and
233+
sense = value.booleanValue()
234+
|
235+
sense = true and succ = pred.getATrueSuccessor()
236+
or
237+
sense = false and succ = pred.getAFalseSuccessor()
238+
)
254239
)
255240
}
256241

@@ -519,13 +504,18 @@ cached module PointsToInternal {
519504
/** Holds if the phi-function `phi` refers to `(value, origin)` given the context `context`. */
520505
pragma [nomagic]
521506
private predicate ssa_phi_points_to(PhiFunction phi, PointsToContext context, ObjectInternal value, CfgOrigin origin) {
522-
exists(EssaVariable input, BasicBlock pred |
523-
input = phi.getInput(pred) and
507+
exists(EssaVariable input |
508+
ssa_phi_reachable_from_input(phi, context, input) and
524509
variablePointsTo(input, context, value, origin)
525-
|
526-
controlledReachableEdge(pred, phi.getBasicBlock(), context)
527-
or
528-
not exists(ConditionBlock guard | guard.controlsEdge(pred, phi.getBasicBlock(), _))
510+
)
511+
}
512+
513+
/* Helper for ssa_phi_points_to */
514+
pragma [noinline]
515+
private predicate ssa_phi_reachable_from_input(PhiFunction phi, PointsToContext context, EssaVariable input) {
516+
exists(BasicBlock pred |
517+
input = phi.getInput(pred) and
518+
reachableEdge(pred, phi.getBasicBlock(), context)
529519
)
530520
}
531521

@@ -839,9 +829,7 @@ module InterProceduralPointsTo {
839829
predicate parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
840830
self_parameter_points_to(def, context, value, origin)
841831
or
842-
positional_parameter_points_to(def, context, value, origin)
843-
or
844-
named_parameter_points_to(def, context, value, origin)
832+
normal_parameter_points_to(def, context, value, origin)
845833
or
846834
default_parameter_points_to(def, context, value, origin)
847835
or
@@ -850,7 +838,7 @@ module InterProceduralPointsTo {
850838

851839
/** Helper for `parameter_points_to` */
852840
pragma [noinline]
853-
private predicate positional_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
841+
private predicate normal_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
854842
exists(PointsToContext caller, ControlFlowNode arg |
855843
PointsToInternal::pointsTo(arg, caller, value, origin) and
856844
callsite_argument_transfer(arg, caller, def, context)
@@ -882,16 +870,6 @@ module InterProceduralPointsTo {
882870
)
883871
}
884872

885-
/** Helper for `parameter_points_to` */
886-
pragma [noinline]
887-
private predicate named_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
888-
exists(CallNode call, PointsToContext caller, PythonFunctionObjectInternal func, string name |
889-
context.fromCall(call, func, caller) and
890-
def.getParameter() = func.getScope().getArgByName(name) and
891-
PointsToInternal::pointsTo(call.getArgByName(name), caller, value, origin)
892-
)
893-
}
894-
895873
/** Helper for parameter_points_to */
896874
pragma [noinline]
897875
private predicate default_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
@@ -939,10 +917,18 @@ module InterProceduralPointsTo {
939917

940918
/** Holds if the `(argument, caller)` pair matches up with `(param, callee)` pair across call. */
941919
cached predicate callsite_argument_transfer(ControlFlowNode argument, PointsToContext caller, ParameterDefinition param, PointsToContext callee) {
942-
exists(CallNode call, Function func, int n, int offset |
943-
callsite_calls_function(call, caller, func, callee, offset) and
944-
argument = call.getArg(n) and
945-
param.getParameter() = func.getArg(n+offset)
920+
exists(CallNode call, Function func, int offset |
921+
callsite_calls_function(call, caller, func, callee, offset)
922+
|
923+
exists(int n |
924+
argument = call.getArg(n) and
925+
param.getParameter() = func.getArg(n+offset)
926+
)
927+
or
928+
exists(string name |
929+
argument = call.getArgByName(name) and
930+
param.getParameter() = func.getArgByName(name)
931+
)
946932
)
947933
}
948934

@@ -1334,6 +1320,7 @@ module Expressions {
13341320
val.strValue() = other.strValue() and result = 1
13351321
}
13361322

1323+
pragma [nomagic]
13371324
private int compare_sequence(SequenceObjectInternal val, SequenceObjectInternal other, int n) {
13381325
inequalityTest(_, _, _, val, other, _, _) and
13391326
(
@@ -1342,11 +1329,17 @@ module Expressions {
13421329
n = other.length() and val.length() > n and result = 1
13431330
or
13441331
n = other.length() and n = val.length() and result = 0
1345-
or
1346-
result != 0 and result = compare_unbound(val.getItem(n), other.getItem(n))
1347-
or
1348-
compare_unbound(val.getItem(n), other.getItem(n)) = 0 and result = compare_sequence(val, other, n+1)
13491332
)
1333+
or
1334+
result != 0 and result = compare_item(val, other, n)
1335+
or
1336+
compare_item(val, other, n) = 0 and result = compare_sequence(val, other, n+1)
1337+
}
1338+
1339+
pragma [noinline]
1340+
private int compare_item(SequenceObjectInternal val, SequenceObjectInternal other, int n) {
1341+
inequalityTest(_, _, _, val, other, _, _) and
1342+
result = compare_unbound(val.getItem(n), other.getItem(n))
13501343
}
13511344

13521345
pragma [noinline]

0 commit comments

Comments
 (0)