From 4296ac1ac0aa24ef3ac41641cf60e292a63fb643 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 12 Sep 2022 15:03:13 +0200 Subject: [PATCH] Python: Allow `CallNode.getArgByName` for keyword args after `**kwargs` --- .../ql/lib/change-notes/2022-09-12-CallNode-getArgByName.md | 4 ++++ python/ql/lib/semmle/python/Flow.qll | 2 +- .../ql/test/experimental/dataflow/coverage/argumentPassing.py | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 python/ql/lib/change-notes/2022-09-12-CallNode-getArgByName.md 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