diff --git a/python/ql/lib/change-notes/2022-09-12-CallNode-getArgByName.md b/python/ql/lib/change-notes/2022-09-12-CallNode-getArgByName.md new file mode 100644 index 00000000000..4bcde8386a8 --- /dev/null +++ b/python/ql/lib/change-notes/2022-09-12-CallNode-getArgByName.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Changed `CallNode.getArgByName` such that it has results for keyword arguments given after a dictionary unpacking argument, as the `bar=2` argument in `func(foo=1, **kwargs, bar=2)`. diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll index ce886151135..b63a958efe6 100644 --- a/python/ql/lib/semmle/python/Flow.qll +++ b/python/ql/lib/semmle/python/Flow.qll @@ -376,7 +376,7 @@ class CallNode extends ControlFlowNode { ControlFlowNode getArgByName(string name) { exists(Call c, Keyword k | this.getNode() = c and - k = c.getAKeyword() and + k = c.getANamedArg() and k.getValue() = result.getNode() and k.getArg() = name and result.getBasicBlock().dominates(this.getBasicBlock()) diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py index 1962bf2889e..92b466cd25a 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py @@ -94,7 +94,7 @@ def with_multiple_kw_args(a, b, c): def test_multiple_kw_args(): with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1 arg2 arg3 with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1 MISSING: arg2 arg3 - with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1 arg3 func=with_multiple_kw_args MISSING: arg2 + with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1 arg2 arg3 func=with_multiple_kw_args MISSING: with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) #$ arg1 arg2 arg3 func=with_multiple_kw_args