mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #16010 from RasmusWL/perf
Python: Two small join-order fixes
This commit is contained in:
@@ -876,7 +876,7 @@ private module TrackAttrReadInput implements CallGraphConstruction::Simple::Inpu
|
||||
|
||||
predicate start(Node start, AttrRead attr) {
|
||||
start = attr and
|
||||
attr.getObject() in [
|
||||
pragma[only_bind_into](attr.getObject()) in [
|
||||
classTracker(_), classInstanceTracker(_), selfTracker(_), clsArgumentTracker(_),
|
||||
superCallNoArgumentTracker(_), superCallTwoArgumentTracker(_, _)
|
||||
]
|
||||
@@ -1302,9 +1302,7 @@ predicate getCallArg(CallNode call, Function target, CallType type, Node arg, Ar
|
||||
//
|
||||
// call_func(my_obj.some_method)
|
||||
// ```
|
||||
exists(CfgNode cfgNode | cfgNode.getNode() = call |
|
||||
cfgNode.getEnclosingCallable() = arg.getEnclosingCallable()
|
||||
)
|
||||
exists(CfgNode cfgNode | cfgNode.getNode() = call | sameEnclosingCallable(cfgNode, arg))
|
||||
or
|
||||
// cls argument for classmethod calls -- see note above about bound methods
|
||||
type instanceof CallTypeClassMethod and
|
||||
@@ -1312,9 +1310,7 @@ predicate getCallArg(CallNode call, Function target, CallType type, Node arg, Ar
|
||||
resolveMethodCall(call, target, type, arg) and
|
||||
(arg = classTracker(_) or arg = clsArgumentTracker(_)) and
|
||||
// dataflow lib has requirement that arguments and calls are in same enclosing callable.
|
||||
exists(CfgNode cfgNode | cfgNode.getNode() = call |
|
||||
cfgNode.getEnclosingCallable() = arg.getEnclosingCallable()
|
||||
)
|
||||
exists(CfgNode cfgNode | cfgNode.getNode() = call | sameEnclosingCallable(cfgNode, arg))
|
||||
or
|
||||
// normal arguments for method calls
|
||||
(
|
||||
@@ -1365,6 +1361,16 @@ predicate getCallArg(CallNode call, Function target, CallType type, Node arg, Ar
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* join-order helper for getCallArg, since otherwise we would do cartesian product of
|
||||
* the enclosing callables
|
||||
*/
|
||||
bindingset[node1, node2]
|
||||
pragma[inline_late]
|
||||
private predicate sameEnclosingCallable(Node node1, Node node2) {
|
||||
node1.getEnclosingCallable() = node2.getEnclosingCallable()
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// DataFlowCall
|
||||
// =============================================================================
|
||||
|
||||
@@ -113,15 +113,25 @@ module SqlAlchemy {
|
||||
*/
|
||||
abstract class InstanceSource extends DataFlow::LocalSourceNode { }
|
||||
|
||||
/**
|
||||
* join-ordering helper for ConnectionConstruction char-pred -- without this would
|
||||
* start with _all_ `CallCfgNode` and join those with `MethodCallNode` .. which is
|
||||
* silly
|
||||
*/
|
||||
pragma[noinline]
|
||||
private DataFlow::MethodCallNode connectionConstruction_helper() {
|
||||
result.calls(Engine::instance(), ["begin", "connect"])
|
||||
or
|
||||
result.calls(instance(), ["connect", "execution_options"])
|
||||
}
|
||||
|
||||
private class ConnectionConstruction extends InstanceSource, DataFlow::CallCfgNode {
|
||||
ConnectionConstruction() {
|
||||
this = classRef().getACall()
|
||||
// without the `pragma[only_bind_out]` we would start with joining
|
||||
// `API::Node.getACall` with `CallCfgNode` which is not optimal
|
||||
this = pragma[only_bind_out](classRef()).getACall()
|
||||
or
|
||||
this.(DataFlow::MethodCallNode).calls(Engine::instance(), ["begin", "connect"])
|
||||
or
|
||||
this.(DataFlow::MethodCallNode).calls(instance(), "connect")
|
||||
or
|
||||
this.(DataFlow::MethodCallNode).calls(instance(), "execution_options")
|
||||
this = connectionConstruction_helper()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user