Skip to content

Commit 04fc1e4

Browse files
authored
Merge pull request #4683 from RasmusWL/python-fix-bad-join-callStep-for-dist-upgrade
Python: Fix bad join order in TypeTracker::callStep
2 parents ab715ec + ab856d6 commit 04fc1e4

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

python/ql/src/semmle/python/dataflow/new/TypeTracker.qll

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,26 @@ private predicate typePreservingStep(Node nodeFrom, Node nodeTo) {
8787
nodeFrom = nodeTo.(PostUpdateNode).getPreUpdateNode()
8888
}
8989

90+
/**
91+
* Gets a callable for the call where `nodeFrom` is used as the `i`'th argument.
92+
*
93+
* Helper predicate to avoid bad join order experienced in `callStep`.
94+
* This happened when `isParameterOf` was joined _before_ `getCallable`.
95+
*/
96+
pragma[nomagic]
97+
private DataFlowCallable getCallableForArgument(ArgumentNode nodeFrom, int i) {
98+
exists(DataFlowCall call |
99+
nodeFrom.argumentOf(call, i) and
100+
result = call.getCallable()
101+
)
102+
}
103+
90104
/** Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call. */
91105
predicate callStep(ArgumentNode nodeFrom, ParameterNode nodeTo) {
92106
// TODO: Support special methods?
93-
exists(DataFlowCall call, int i |
94-
nodeFrom.argumentOf(call, i) and nodeTo.isParameterOf(call.getCallable(), i)
107+
exists(DataFlowCallable callable, int i |
108+
callable = getCallableForArgument(nodeFrom, i) and
109+
nodeTo.isParameterOf(callable, i)
95110
)
96111
}
97112

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
def foo(foo_x): # $tracked
2+
print("foo", foo_x) # $tracked
3+
4+
5+
def bar(bar_x): # $tracked
6+
print("bar", bar_x) # $tracked
7+
8+
9+
if len(__file__) % 2 == 0:
10+
f = foo
11+
else:
12+
f = bar
13+
14+
x = tracked # $tracked
15+
f(x) # $tracked

0 commit comments

Comments
 (0)