Skip to content

Commit 07e3829

Browse files
committed
python: add read steps for some specific functions
1 parent e791039 commit 07e3829

File tree

5 files changed

+82
-10
lines changed

5 files changed

+82
-10
lines changed

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

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4260,6 +4260,15 @@ module StdlibPrivate {
42604260
output = "ReturnValue.ListElement" and
42614261
preservesValue = true
42624262
or
4263+
// in case we create a list from a container with precise elementt,
4264+
// we need to taint the list.
4265+
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
4266+
input = "Argument[0].TupleElement[" + i.toString() + "]"
4267+
) and
4268+
// TODO: Once we have DictKeyContent, we need to transform that into taint
4269+
output = "ReturnValue" and
4270+
preservesValue = false
4271+
or
42634272
input = "Argument[0]" and
42644273
output = "ReturnValue" and
42654274
preservesValue = false
@@ -4708,8 +4717,13 @@ module StdlibPrivate {
47084717
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
47094718
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
47104719
input = "Argument[self].DictionaryElement[" + key + "]" and
4711-
output = "ReturnValue.ListElement" and
4712-
preservesValue = true
4720+
(
4721+
output = "ReturnValue.ListElement" and
4722+
preservesValue = true
4723+
or
4724+
output = "ReturnValue" and
4725+
preservesValue = false
4726+
)
47134727
)
47144728
or
47154729
input = "Argument[self]" and
@@ -4759,8 +4773,13 @@ module StdlibPrivate {
47594773
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
47604774
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
47614775
input = "Argument[self].DictionaryElement[" + key + "]" and
4762-
output = "ReturnValue.ListElement.TupleElement[1]" and
4763-
preservesValue = true
4776+
(
4777+
output = "ReturnValue.ListElement.TupleElement[1]" and
4778+
preservesValue = true
4779+
or
4780+
output = "ReturnValue" and
4781+
preservesValue = false
4782+
)
47644783
)
47654784
or
47664785
// TODO: Add the keys to output list
@@ -4826,6 +4845,50 @@ module StdlibPrivate {
48264845
}
48274846
}
48284847

4848+
// ---------------------------------------------------------------------------
4849+
// Flow summaries for string methods
4850+
// ---------------------------------------------------------------------------
4851+
class StringManipulation extends SummarizedCallable {
4852+
string method_name;
4853+
4854+
StringManipulation() {
4855+
this = "string." + method_name and
4856+
method_name in [
4857+
"capitalize", "casefold", "center", "expandtabs", "format", "format_map", "join", "ljust",
4858+
"lstrip", "lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper",
4859+
"zfill", "encode", "decode"
4860+
]
4861+
}
4862+
4863+
override DataFlow::CallCfgNode getACall() {
4864+
result.(DataFlow::MethodCallNode).calls(_, method_name)
4865+
}
4866+
4867+
override DataFlow::ArgumentNode getACallback() {
4868+
result.(DataFlow::AttrRead).getAttributeName() = method_name
4869+
}
4870+
4871+
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
4872+
input = "Argument[self]" and
4873+
output = "ReturnValue" and
4874+
preservesValue = false
4875+
or
4876+
method_name = "join" and
4877+
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
4878+
input = "Argument[0].TupleElement[" + i + "]"
4879+
) and
4880+
output = "ReturnValue" and
4881+
preservesValue = false
4882+
or
4883+
method_name = "format_map" and
4884+
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
4885+
input = "Argument[0].DictionaryElement[" + key + "]"
4886+
) and
4887+
output = "ReturnValue" and
4888+
preservesValue = false
4889+
}
4890+
}
4891+
48294892
/**
48304893
* A flow summary for `os.getenv` / `os.getenvb`
48314894
*

python/ql/test/library-tests/dataflow/sensitive-data/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,4 @@ def call_wrapper(func):
133133

134134
# since we have taint-step from store of `password`, we will consider any item in the
135135
# dictionary to be a password :(
136-
print(_config["sleep_timer"]) # $ SPURIOUS: SensitiveUse=password
136+
print(_config["sleep_timer"])

python/ql/test/library-tests/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ def test_construction():
2222
ensure_tainted(
2323
tainted_string, # $ tainted
2424
tainted_list, # $ tainted
25-
tainted_tuple, # $ tainted
25+
tainted_tuple[0], # $ tainted
2626
tainted_set, # $ tainted
27-
tainted_dict, # $ tainted
27+
tainted_dict["key"], # $ tainted
2828
)
2929

3030
ensure_tainted(
@@ -37,13 +37,22 @@ def test_construction():
3737
tuple(tainted_list), # $ tainted
3838
set(tainted_list), # $ tainted
3939
frozenset(tainted_list), # $ tainted
40-
dict(tainted_dict), # $ tainted
40+
dict(tainted_dict)["key"], # $ tainted
4141
dict(k = tainted_string)["k"], # $ tainted
4242
dict(dict(k = tainted_string))["k"], # $ tainted
4343
dict(["k", tainted_string]), # $ tainted
4444
)
4545

4646
ensure_not_tainted(
47+
tainted_tuple,
48+
tainted_tuple[1],
49+
50+
tainted_dict,
51+
tainted_dict["different_key"],
52+
53+
dict(tainted_dict),
54+
dict(tainted_dict)["different_key"],
55+
4756
dict(k = tainted_string)["k1"]
4857
)
4958

python/ql/test/library-tests/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def percent_fmt():
115115
ensure_tainted(
116116
tainted_fmt % (1, 2), # $ tainted
117117
"%s foo bar" % ts, # $ tainted
118-
"%s %s %s" % (1, 2, ts), # $ tainted
118+
"%s %s %s" % (1, 2, ts), # $ MISSING: tainted
119119
)
120120

121121

python/ql/test/library-tests/dataflow/tainttracking/defaultAdditionalTaintStep/test_unpacking.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def contrived_1():
5353

5454
(a, b, c), (d, e, f) = tainted_list, no_taint_list
5555
ensure_tainted(a, b, c) # $ tainted
56-
ensure_not_tainted(d, e, f) # $ SPURIOUS: tainted
56+
ensure_not_tainted(d, e, f)
5757

5858

5959
def contrived_2():

0 commit comments

Comments
 (0)