Skip to content

Commit 9e2eb56

Browse files
committed
Python: Remove support for late *args arguments
I found this to cause bad performance, so the implementation of this has to be thought out more carefully.
1 parent 5c23b47 commit 9e2eb56

File tree

4 files changed

+1
-77
lines changed

4 files changed

+1
-77
lines changed

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ newtype TParameterPosition =
6464
index = any(Parameter p).getPosition() + 1
6565
} or
6666
TSynthStarArgsElementParameterPosition(int index) { exists(TStarArgsParameterPosition(index)) } or
67-
TSynthLateStarArgsParameterPosition(int index) { exists(TStarArgsParameterPosition(index)) } or
6867
TDictSplatParameterPosition()
6968

7069
/** A parameter position. */
@@ -90,14 +89,6 @@ class ParameterPosition extends TParameterPosition {
9089
this = TSynthStarArgsElementParameterPosition(index)
9190
}
9291

93-
/**
94-
* Holds if this position represents a synthetic `*args` parameter after the real
95-
* `*args` parameter. The real `*args` parameter is at the 0-based index `index`.
96-
*/
97-
predicate isSynthLateStarArgsParameterPosition(int index) {
98-
this = TSynthLateStarArgsParameterPosition(index)
99-
}
100-
10192
/** Holds if this position represents a `**kwargs` parameter. */
10293
predicate isDictSplat() { this = TDictSplatParameterPosition() }
10394

@@ -116,11 +107,6 @@ class ParameterPosition extends TParameterPosition {
116107
result = "synthetic *args element at (or after) " + index
117108
)
118109
or
119-
exists(int index |
120-
this.isSynthLateStarArgsParameterPosition(index) and
121-
result = "synthetic late *args after " + index
122-
)
123-
or
124110
this.isDictSplat() and result = "**"
125111
}
126112
}
@@ -192,10 +178,6 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
192178
ppos.isSynthStarArgsElement(paramIndex) and apos.isPositional(argIndex)
193179
)
194180
or
195-
exists(int realStarArgsIndex, int argIndex | argIndex > realStarArgsIndex |
196-
ppos.isSynthLateStarArgsParameterPosition(realStarArgsIndex) and apos.isStarArgs(argIndex)
197-
)
198-
or
199181
ppos.isDictSplat() and apos.isDictSplat()
200182
}
201183

@@ -329,9 +311,6 @@ abstract class DataFlowFunction extends DataFlowCallable, TFunction {
329311
or
330312
ppos.isSynthStarArgsElement(index) and
331313
result = TSynthStarArgsElementParameterNode(this)
332-
or
333-
ppos.isSynthLateStarArgsParameterPosition(index) and
334-
result = TSynthLateStarArgsParameterNode(this)
335314
)
336315
|
337316
// a `*args` parameter comes after the last positional parameter. We need to take

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -135,49 +135,6 @@ predicate synthStarArgsElementParameterNodeStoreStep(
135135
)
136136
}
137137

138-
/**
139-
* A synthetic node to capture a `*args` argument that is passed to a `*args`
140-
* parameter, but "too late" in the argument list, so we cannot just do a 1-1 mapping
141-
* without messing up the indexes; instead we make a list/tuple/set read step to
142-
* `SynthStarArgsElementParameterNode`.
143-
*
144-
* Example. The `*args` arguments starts at index 1, while the `*args` parameter accepts
145-
* arguments starting at index 0.
146-
*
147-
* ```py
148-
* def func(*args): ...
149-
* func(1, *args)
150-
*/
151-
class SynthLateStarArgsParameterNode extends ParameterNodeImpl, TSynthLateStarArgsParameterNode {
152-
DataFlowCallable callable;
153-
154-
SynthLateStarArgsParameterNode() { this = TSynthLateStarArgsParameterNode(callable) }
155-
156-
override string toString() { result = "SynthLateStarArgsParameterNode" }
157-
158-
override Scope getScope() { result = callable.getScope() }
159-
160-
override Location getLocation() { result = callable.getLocation() }
161-
162-
override Parameter getParameter() { none() }
163-
}
164-
165-
predicate synthLateStarArgsParameterNodeReadStep(
166-
SynthLateStarArgsParameterNode nodeFrom, Content c, ParameterNode nodeTo
167-
) {
168-
(
169-
c instanceof ListElementContent
170-
or
171-
c instanceof TupleElementContent
172-
or
173-
c instanceof SetElementContent
174-
) and
175-
exists(DataFlowCallable callable |
176-
nodeFrom = TSynthLateStarArgsParameterNode(callable) and
177-
nodeTo = TSynthStarArgsElementParameterNode(callable)
178-
)
179-
}
180-
181138
// =============================================================================
182139
// **kwargs (DictSplat) related
183140
// =============================================================================
@@ -843,8 +800,6 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
843800
or
844801
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom, c, nodeTo)
845802
or
846-
synthLateStarArgsParameterNodeReadStep(nodeFrom, c, nodeTo)
847-
or
848803
synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo)
849804
}
850805

@@ -1006,8 +961,6 @@ predicate nodeIsHidden(Node n) {
1006961
or
1007962
n instanceof SynthStarArgsElementParameterNode
1008963
or
1009-
n instanceof SynthLateStarArgsParameterNode
1010-
or
1011964
n instanceof SynthDictSplatArgumentNode
1012965
or
1013966
n instanceof SynthDictSplatParameterNode

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,6 @@ newtype TNode =
117117
TSynthStarArgsElementParameterNode(DataFlowCallable callable) {
118118
exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos)))
119119
} or
120-
/**
121-
* A synthetic node to capture a `*args` argument that is passed to a `*args`
122-
* parameter, but "too late" in the argument list, so we cannot just do a 1-1 mapping
123-
* without messing up the indexes.
124-
*/
125-
TSynthLateStarArgsParameterNode(DataFlowCallable callable) {
126-
exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos)))
127-
} or
128120
/** A synthetic node to capture keyword arguments that are passed to a `**kwargs` parameter. */
129121
TSynthDictSplatArgumentNode(CallNode call) { exists(call.getArgByName(_)) } or
130122
/** A synthetic node to allow flow to keyword parameters from a `**kwargs` argument. */

python/ql/test/experimental/dataflow/coverage/argumentPassing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def starargs_only(*args):
213213
def test_only_starargs():
214214
starargs_only(arg1, arg2, "safe") # $ arg1 arg2 SPURIOUS: bad2,bad3="arg1" bad1,bad3="arg2"
215215

216-
args = (arg2, "safe") # $ arg2 func=starargs_only SPURIOUS: bad1,bad3="arg2"
216+
args = (arg2, "safe") # $ MISSING: arg2
217217
starargs_only(arg1, *args) # $ arg1 SPURIOUS: bad2,bad3="arg1"
218218

219219
args = (arg1, arg2, "safe") # $ arg1 arg2 func=starargs_only

0 commit comments

Comments
 (0)