Merge pull request #17566 from yoff/python/dict-can-take-multiple-args

Python: All dict constructor args are relevant
This commit is contained in:
yoff
2024-10-04 14:30:10 +02:00
committed by GitHub
3 changed files with 21 additions and 5 deletions

View File

@@ -368,14 +368,13 @@ abstract class DataFlowFunction extends DataFlowCallable, TFunction {
int positionalOffset() { result = 0 }
override ParameterNode getParameter(ParameterPosition ppos) {
// Do not handle lower bound positions (such as `[1..]`) here
// they are handled by parameter matching and would create
// inconsistencies here as multiple parameters could match such a position.
exists(int index | ppos.isPositional(index) |
result.getParameter() = func.getArg(index + this.positionalOffset())
)
or
exists(int index1, int index2 | ppos.isPositionalLowerBound(index1) and index2 >= index1 |
result.getParameter() = func.getArg(index2 + this.positionalOffset())
)
or
exists(string name | ppos.isKeyword(name) | result.getParameter() = func.getArgByName(name))
or
// `*args`

View File

@@ -4235,7 +4235,11 @@ module StdlibPrivate {
// ---------------------------------------------------------------------------
// Flow summaries for functions contructing containers
// ---------------------------------------------------------------------------
/** A flow summary for `dict`. */
/**
* A flow summary for `dict`.
*
* see https://docs.python.org/3/library/stdtypes.html#dict
*/
class DictSummary extends SummarizedCallable {
DictSummary() { this = "builtins.dict" }
@@ -4246,18 +4250,23 @@ module StdlibPrivate {
}
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
// The positional argument contains a mapping.
// TODO: Add the list-of-pairs version
// TODO: these values can be overwritten by keyword arguments
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
input = "Argument[0].DictionaryElement[" + key + "]" and
output = "ReturnValue.DictionaryElement[" + key + "]" and
preservesValue = true
)
or
// The keyword arguments are added to the dictionary.
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
input = "Argument[" + key + ":]" and
output = "ReturnValue.DictionaryElement[" + key + "]" and
preservesValue = true
)
or
// Imprecise content in any argument ends up on the container itself.
input = "Argument[0]" and
output = "ReturnValue" and
preservesValue = false

View File

@@ -142,6 +142,14 @@ def test_dict_from_dict():
SINK(d2["k"]) #$ flow="SOURCE, l:-2 -> d2['k']"
SINK_F(d2["k1"])
@expects(4)
def test_dict_from_multiple_args():
d = dict([("k", SOURCE), ("k1", NONSOURCE)], k2 = SOURCE, k3 = NONSOURCE)
SINK(d["k"]) #$ MISSING: flow="SOURCE, l:-1 -> d['k']"
SINK_F(d["k1"])
SINK(d["k2"]) #$ flow="SOURCE, l:-3 -> d['k2']"
SINK_F(d["k3"])
## Container methods
### List