mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #969 from markshannon/python-points-to-speed-up
Python: Refactor three predicates to improve join-order.
This commit is contained in:
@@ -1023,6 +1023,20 @@ class BasicBlock extends @py_flow_node {
|
|||||||
predicate likelyReachable() {
|
predicate likelyReachable() {
|
||||||
start_bb_likely_reachable(this)
|
start_bb_likely_reachable(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gets the `ConditionBlock`, if any, that controls this block and
|
||||||
|
* does not control any other `ConditionBlock`s that control this block.
|
||||||
|
* That is the `ConditionBlock` that is closest dominator.
|
||||||
|
*/
|
||||||
|
ConditionBlock getImmediatelyControllingBlock() {
|
||||||
|
result = this.nonControllingImmediateDominator*().getImmediateDominator()
|
||||||
|
}
|
||||||
|
|
||||||
|
private BasicBlock nonControllingImmediateDominator() {
|
||||||
|
result = this.getImmediateDominator() and
|
||||||
|
not result.(ConditionBlock).controls(this, _)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate start_bb_likely_reachable(BasicBlock b) {
|
private predicate start_bb_likely_reachable(BasicBlock b) {
|
||||||
|
|||||||
@@ -447,10 +447,13 @@ module PointsTo {
|
|||||||
private module Layer {
|
private module Layer {
|
||||||
|
|
||||||
/* Holds if BasicBlock `b` is reachable, given the context `context`. */
|
/* Holds if BasicBlock `b` is reachable, given the context `context`. */
|
||||||
predicate reachableBlock(BasicBlock b, PointsToContext context) {
|
predicate reachableBlock(BasicBlock b, PointsToContext context) {
|
||||||
context.appliesToScope(b.getScope()) and
|
context.appliesToScope(b.getScope()) and not exists(ConditionBlock guard | guard.controls(b, _))
|
||||||
forall(ConditionBlock guard |
|
or
|
||||||
guard.controls(b, _) |
|
exists(ConditionBlock guard |
|
||||||
|
guard = b.getImmediatelyControllingBlock() and
|
||||||
|
reachableBlock(guard, context)
|
||||||
|
|
|
||||||
exists(Object value |
|
exists(Object value |
|
||||||
points_to(guard.getLastNode(), context, value, _, _)
|
points_to(guard.getLastNode(), context, value, _, _)
|
||||||
|
|
|
|
||||||
@@ -1827,21 +1830,27 @@ module PointsTo {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma [noinline]
|
/** Holds if `call`, in `context` is a call to a function that does not modify the refined variable */
|
||||||
private predicate callsite_points_to_python(CallsiteRefinement def, PointsToContext context, Object value, ClassObject cls, CfgOrigin origin) {
|
private predicate call_to_safe_function(CallsiteRefinement def, PointsToContext context) {
|
||||||
ssa_variable_points_to(def.getInput(), context, value, cls, origin) and
|
exists(CallNode call |
|
||||||
exists(CallNode call, PythonSsaSourceVariable var |
|
|
||||||
call = def.getCall() and
|
call = def.getCall() and
|
||||||
var = def.getSourceVariable() and
|
|
||||||
context.untrackableCall(call) and
|
context.untrackableCall(call) and
|
||||||
exists(PyFunctionObject modifier, Function f |
|
exists(PyFunctionObject modifier, Function f |
|
||||||
f = modifier.getFunction() and
|
f = modifier.getFunction() and
|
||||||
call = get_a_call(modifier, context) and
|
call = get_a_call(modifier, context) and
|
||||||
not modifies_escaping_variable(f, var)
|
not modifies_escaping_variable(f, def.getSourceVariable())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private predicate callsite_points_to_python(CallsiteRefinement def, PointsToContext context, Object value, ClassObject cls, CfgOrigin origin) {
|
||||||
|
exists(EssaVariable input |
|
||||||
|
input = def.getInput() and
|
||||||
|
ssa_variable_points_to(input, context, value, cls, origin) and
|
||||||
|
call_to_safe_function(def, context)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate modifies_escaping_variable(Function modifier, PythonSsaSourceVariable var) {
|
private predicate modifies_escaping_variable(Function modifier, PythonSsaSourceVariable var) {
|
||||||
exists(var.redefinedAtCallSite()) and
|
exists(var.redefinedAtCallSite()) and
|
||||||
modifier.getBody().contains(var.(Variable).getAStore())
|
modifier.getBody().contains(var.(Variable).getAStore())
|
||||||
@@ -2987,19 +2996,21 @@ class SuperBoundMethod extends Object {
|
|||||||
|
|
||||||
SuperCall superObject;
|
SuperCall superObject;
|
||||||
string name;
|
string name;
|
||||||
|
ClassObject startType;
|
||||||
|
|
||||||
cached
|
cached
|
||||||
SuperBoundMethod() {
|
SuperBoundMethod() {
|
||||||
exists(ControlFlowNode object |
|
exists(ControlFlowNode object |
|
||||||
this.(AttrNode).getObject(name) = object |
|
this.(AttrNode).getObject(name) = object |
|
||||||
PointsTo::points_to(object, _, superObject, _, _)
|
PointsTo::points_to(object, _, superObject, _, _) and
|
||||||
|
startType = superObject.startType()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionObject getFunction(PointsToContext ctx) {
|
FunctionObject getFunction(PointsToContext ctx) {
|
||||||
exists(ClassList mro |
|
exists(ClassList mro |
|
||||||
mro = PointsTo::Types::get_mro(superObject.selfType(ctx)) |
|
mro = PointsTo::Types::get_mro(superObject.selfType(ctx)) |
|
||||||
result = mro.startingAt(superObject.startType()).getTail().lookup(name)
|
result = mro.startingAt(startType).getTail().lookup(name)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user