mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Python: Fix bad join order in TypeTracker::callStep
From a local evaluation against flask DB, after https://github.com/github/codeql/pull/4649 was merged we would get: ``` Tuple counts for TypeTracker::callStep#ff/2@a21b71: 9876 ~0% {3} r1 = SCAN DataFlowPrivate::DataFlowCall::getArg_dispred#fff AS I OUTPUT I.<2>, I.<0>, I.<1> 9876 ~2% {3} r2 = JOIN r1 WITH project#DataFlowPrivate::DataFlowCall::getArg_dispred#fff AS R ON FIRST 1 OUTPUT r1.<2>, R.<0>, r1.<1> 72388997 ~0% {4} r3 = JOIN r2 WITH DataFlowPublic::ParameterNode::isParameterOf_dispred#fff_201#join_rhs AS R ON FIRST 1 OUTPUT r2.<2>, R.<2>, r2.<1>, R.<1> 4952 ~0% {2} r4 = JOIN r3 WITH DataFlowPrivate::DataFlowCall::getCallable_dispred#ff AS R ON FIRST 2 OUTPUT r3.<2>, r3.<3> return r4 ```
This commit is contained in:
@@ -87,11 +87,25 @@ private predicate typePreservingStep(Node nodeFrom, Node nodeTo) {
|
||||
nodeFrom = nodeTo.(PostUpdateNode).getPreUpdateNode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper predicate to avoid bad join order experienced in `callStep`.
|
||||
*
|
||||
* This happened when `isParameterOf` was joined _before_ `getCallable`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private DataFlowCallable callStepHelper(ArgumentNode nodeFrom, int i) {
|
||||
exists(DataFlowCall call |
|
||||
nodeFrom.argumentOf(call, i) and
|
||||
result = call.getCallable()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call. */
|
||||
predicate callStep(ArgumentNode nodeFrom, ParameterNode nodeTo) {
|
||||
// TODO: Support special methods?
|
||||
exists(DataFlowCall call, int i |
|
||||
nodeFrom.argumentOf(call, i) and nodeTo.isParameterOf(call.getCallable(), i)
|
||||
exists(DataFlowCallable callable, int i |
|
||||
callable = callStepHelper(nodeFrom, i) and
|
||||
nodeTo.isParameterOf(callable, i)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user