Skip to content

Commit 0094271

Browse files
committed
Python: Port WrongNameForArgumentInClassInstantiation.ql
1 parent 6c56882 commit 0094271

File tree

3 files changed

+36
-8
lines changed

3 files changed

+36
-8
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,4 +2111,10 @@ module DuckTyping {
21112111
)
21122112
)
21132113
}
2114+
2115+
/**
2116+
* Gets the `__init__` function that will be invoked when `cls` is constructed,
2117+
* resolved according to the MRO.
2118+
*/
2119+
Function getInit(Class cls) { result = invokedFunctionFromClassConstruction(cls, "__init__") }
21142120
}

python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,34 @@
1515
*/
1616

1717
import python
18-
import Expressions.CallArgs
19-
private import LegacyPointsTo
18+
private import semmle.python.dataflow.new.internal.DataFlowDispatch
2019

21-
from Call call, ClassValue cls, string name, FunctionValue init
20+
/**
21+
* Holds if `name` is a legal argument name for calling `init`.
22+
*/
23+
bindingset[name]
24+
predicate isLegalArgumentName(Function init, string name) {
25+
exists(init.getArgByName(name))
26+
or
27+
init.hasKwArg()
28+
}
29+
30+
/**
31+
* Holds if `call` constructs class `cls` and passes a keyword argument `name`
32+
* that does not correspond to any parameter of `cls.__init__`.
33+
*/
34+
predicate illegally_named_parameter(Call call, Class cls, string name) {
35+
exists(Function init |
36+
resolveClassCall(call.getAFlowNode(), cls) and
37+
init = DuckTyping::getInit(cls) and
38+
name = call.getANamedArgumentName() and
39+
not isLegalArgumentName(init, name)
40+
)
41+
}
42+
43+
from Call call, Class cls, string name, Function init
2244
where
2345
illegally_named_parameter(call, cls, name) and
24-
init = get_function_or_initializer(cls)
46+
init = DuckTyping::getInit(cls)
2547
select call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", init,
2648
init.getQualifiedName()
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| wrong_arguments.py:65:1:65:7 | F0() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:4:5:4:26 | Function F0.__init__ | F0.__init__ |
2-
| wrong_arguments.py:66:1:66:7 | F1() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:8:5:8:36 | Function F1.__init__ | F1.__init__ |
3-
| wrong_arguments.py:67:1:67:12 | F2() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:12:5:12:30 | Function F2.__init__ | F2.__init__ |
4-
| wrong_arguments.py:92:1:92:27 | F6() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ |
1+
| wrong_arguments.py:65:1:65:7 | F0() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:4:5:4:26 | Function __init__ | F0.__init__ |
2+
| wrong_arguments.py:66:1:66:7 | F1() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:8:5:8:36 | Function __init__ | F1.__init__ |
3+
| wrong_arguments.py:67:1:67:12 | F2() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:12:5:12:30 | Function __init__ | F2.__init__ |
4+
| wrong_arguments.py:92:1:92:27 | F6() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ |

0 commit comments

Comments
 (0)