Skip to content

Commit 1a97e8f

Browse files
committed
Python: Add flow-step for arg[1] to dict.setdefault
1 parent 7453533 commit 1a97e8f

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

python/ql/lib/semmle/python/frameworks/Stdlib.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3795,6 +3795,30 @@ private module StdlibPrivate {
37953795
preservesValue = true
37963796
}
37973797
}
3798+
3799+
/**
3800+
* A flow summary for `dict.setdefault`.
3801+
*
3802+
* See https://docs.python.org/3.10/library/stdtypes.html#dict.setdefault
3803+
*/
3804+
class DictSetdefaultSummary extends SummarizedCallable {
3805+
DictSetdefaultSummary() { this = "dict.setdefault" }
3806+
3807+
override DataFlow::CallCfgNode getACall() {
3808+
result.(DataFlow::MethodCallNode).calls(_, "setdefault")
3809+
}
3810+
3811+
override DataFlow::ArgumentNode getACallback() {
3812+
result.(DataFlow::AttrRead).getAttributeName() = "setdefault"
3813+
}
3814+
3815+
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
3816+
// store/read steps with dictionary content of this is modeled in DataFlowPrivate
3817+
input = "Argument[1]" and
3818+
output = "ReturnValue" and
3819+
preservesValue = true
3820+
}
3821+
}
37983822
}
37993823

38003824
// ---------------------------------------------------------------------------

python/ql/test/experimental/dataflow/fieldflow/test_dict.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def test_dict_update():
4949
def test_setdefault():
5050
d = {}
5151
x = d.setdefault("key", SOURCE)
52-
SINK(x) # $ MISSING: flow="SOURCE, l:-1 -> d.setdefault(..)"
52+
SINK(x) # $ flow="SOURCE, l:-1 -> x"
5353
SINK(d["key"]) # $ flow="SOURCE, l:-2 -> d['key']"
5454
SINK(d.setdefault("key", NONSOURCE)) # $ flow="SOURCE, l:-3 -> d.setdefault(..)"
5555

0 commit comments

Comments
 (0)