mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
python: add summaries for
copy, pop, get, getitem, setdefault
Also add read steps to taint tracking.
Reading from a tainted collection can be done in two situations:
1. There is an acces path
In this case a read step (possibly from a flow summary)
gives rise to a taint step.
2. There is no access path
In this case an explicit taint step (possibly via a flow
summary) should exist.
This commit is contained in:
@@ -123,23 +123,23 @@ def test_nested_list_display():
|
||||
# 6.2.6. Set displays
|
||||
def test_set_display():
|
||||
x = {SOURCE}
|
||||
SINK(x.pop()) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension():
|
||||
x = {SOURCE for y in [NONSOURCE]}
|
||||
SINK(x.pop()) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension_flow():
|
||||
x = {y for y in [SOURCE]}
|
||||
SINK(x.pop()) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension_inflow():
|
||||
l = {SOURCE}
|
||||
x = {y for y in l}
|
||||
SINK(x.pop()) #$ MISSING:flow="SOURCE, l:-2 -> x.pop()"
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-2 -> x.pop()"
|
||||
|
||||
|
||||
def test_nested_set_display():
|
||||
@@ -155,7 +155,7 @@ def test_dict_display():
|
||||
|
||||
def test_dict_display_pop():
|
||||
x = {"s": SOURCE}
|
||||
SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:-1 -> x.pop(..)"
|
||||
SINK(x.pop("s")) #$ flow="SOURCE, l:-1 -> x.pop(..)"
|
||||
|
||||
|
||||
def test_dict_comprehension():
|
||||
|
||||
@@ -100,19 +100,19 @@ def test_set_from_list():
|
||||
l = [SOURCE]
|
||||
s = set(l)
|
||||
v = s.pop()
|
||||
SINK(v) #$ MISSING:flow="SOURCE, l:-3 -> v"
|
||||
SINK(v) #$ flow="SOURCE, l:-3 -> v"
|
||||
|
||||
def test_set_from_tuple():
|
||||
t = (SOURCE,)
|
||||
s = set(t)
|
||||
v = s.pop()
|
||||
SINK(v) #$ MISSING:flow="SOURCE, l:-3 -> v"
|
||||
SINK(v) #$ flow="SOURCE, l:-3 -> v"
|
||||
|
||||
def test_set_from_set():
|
||||
s0 = {SOURCE}
|
||||
s = set(s0)
|
||||
v = s.pop()
|
||||
SINK(v) #$ MISSING:flow="SOURCE, l:-3 -> v"
|
||||
SINK(v) #$ flow="SOURCE, l:-3 -> v"
|
||||
|
||||
def test_set_from_dict():
|
||||
d = {SOURCE: "val"}
|
||||
@@ -149,24 +149,24 @@ def test_dict_from_dict():
|
||||
def test_list_pop():
|
||||
l = [SOURCE]
|
||||
v = l.pop()
|
||||
SINK(v) #$ MISSING:flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
|
||||
def test_list_pop_index():
|
||||
l = [SOURCE]
|
||||
v = l.pop(0)
|
||||
SINK(v) #$ MISSING: flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
|
||||
def test_list_pop_index_imprecise():
|
||||
l = [SOURCE, NONSOURCE]
|
||||
v = l.pop(1)
|
||||
SINK_F(v)
|
||||
SINK_F(v) #$ SPURIOUS: flow="SOURCE, l:-2 -> v"
|
||||
|
||||
@expects(2)
|
||||
def test_list_copy():
|
||||
l0 = [SOURCE, NONSOURCE]
|
||||
l = l0.copy()
|
||||
SINK(l[0]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK_F(l[1])
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK_F(l[1]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l[1]"
|
||||
|
||||
def test_list_append():
|
||||
l = [NONSOURCE]
|
||||
@@ -178,12 +178,12 @@ def test_list_append():
|
||||
def test_set_pop():
|
||||
s = {SOURCE}
|
||||
v = s.pop()
|
||||
SINK(v) #$ MISSING:flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
|
||||
def test_set_copy():
|
||||
s0 = {SOURCE}
|
||||
s = s0.copy()
|
||||
SINK(s.pop()) #$ MISSING: flow="SOURCE, l:-2 -> s.pop()"
|
||||
SINK(s.pop()) #$ flow="SOURCE, l:-2 -> s.pop()"
|
||||
|
||||
def test_set_add():
|
||||
s = set([])
|
||||
@@ -218,32 +218,32 @@ def test_dict_items():
|
||||
def test_dict_pop():
|
||||
d = {'k': SOURCE}
|
||||
v = d.pop("k")
|
||||
SINK(v) #$ MISSING:flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
v1 = d.pop("k", NONSOURCE)
|
||||
SINK_F(v1)
|
||||
SINK_F(v1) #$ SPURIOUS: flow="SOURCE, l:-4 -> v1"
|
||||
v2 = d.pop("non-existing", SOURCE)
|
||||
SINK(v2) #$ MISSING: flow="SOURCE, l:-1 -> v2"
|
||||
SINK(v2) #$ flow="SOURCE, l:-1 -> v2"
|
||||
|
||||
@expects(2)
|
||||
def test_dict_get():
|
||||
d = {'k': SOURCE}
|
||||
v = d.get("k")
|
||||
SINK(v) #$ MISSING:flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
v1 = d.get("non-existing", SOURCE)
|
||||
SINK(v1) #$ MISSING: flow="SOURCE, l:-1 -> v1"
|
||||
SINK(v1) #$ flow="SOURCE, l:-1 -> v1"
|
||||
|
||||
@expects(2)
|
||||
def test_dict_popitem():
|
||||
d = {'k': SOURCE}
|
||||
t = d.popitem() # could be any pair (before 3.7), but we only have one
|
||||
SINK_F(t[0])
|
||||
SINK(t[1]) #$ MISSING: flow="SOURCE, l:-3 -> t[1]"
|
||||
SINK(t[1]) #$ flow="SOURCE, l:-3 -> t[1]"
|
||||
|
||||
@expects(2)
|
||||
def test_dict_copy():
|
||||
d = {'k': SOURCE, 'k1': NONSOURCE}
|
||||
d1 = d.copy()
|
||||
SINK(d1["k"]) #$ MISSING: flow="SOURCE, l:-2 -> d[k]"
|
||||
SINK(d1["k"]) #$ flow="SOURCE, l:-2 -> d1['k']"
|
||||
SINK_F(d1["k1"])
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ def SINK_F(x):
|
||||
def test_dict_literal():
|
||||
d = {"key": SOURCE}
|
||||
SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']"
|
||||
SINK(d.get("key")) # $ MISSING:flow="SOURCE, l:-2 -> d.get(..)"
|
||||
SINK(d.get("key")) # $ flow="SOURCE, l:-2 -> d.get(..)"
|
||||
|
||||
|
||||
@expects(2) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..)
|
||||
@@ -43,7 +43,7 @@ def test_dict_update():
|
||||
d = {}
|
||||
d["key"] = SOURCE
|
||||
SINK(d["key"]) # $ flow="SOURCE, l:-1 -> d['key']"
|
||||
SINK(d.get("key")) # $ MISSING:flow="SOURCE, l:-2 -> d.get(..)"
|
||||
SINK(d.get("key")) # $ flow="SOURCE, l:-2 -> d.get(..)"
|
||||
|
||||
@expects(3) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..)
|
||||
def test_dict_setdefault():
|
||||
@@ -51,7 +51,7 @@ def test_dict_setdefault():
|
||||
x = d.setdefault("key", SOURCE)
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
SINK(d["key"]) # $ flow="SOURCE, l:-2 -> d['key']"
|
||||
SINK(d.setdefault("key", NONSOURCE)) # $ MISSING:flow="SOURCE, l:-3 -> d.setdefault(..)"
|
||||
SINK(d.setdefault("key", NONSOURCE)) # $ flow="SOURCE, l:-3 -> d.setdefault(..)"
|
||||
|
||||
@expects(2) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..)
|
||||
def test_dict_override():
|
||||
|
||||
@@ -13,7 +13,7 @@ def test_access():
|
||||
tainted_list = TAINTED_LIST
|
||||
|
||||
ensure_tainted(
|
||||
tainted_list.copy(), # $ MISSING: tainted
|
||||
tainted_list.copy(), # $ tainted
|
||||
)
|
||||
|
||||
for ((x, y, *z), a, b) in tainted_list:
|
||||
|
||||
@@ -103,9 +103,9 @@ def test_dict_access(x):
|
||||
|
||||
ensure_tainted(
|
||||
tainted_dict["name"], # $ tainted
|
||||
tainted_dict.get("name"), # $ MISSING: tainted
|
||||
tainted_dict.get("name"), # $ tainted
|
||||
tainted_dict[x], # $ tainted
|
||||
tainted_dict.copy(), # $ MISSING: tainted
|
||||
tainted_dict.copy(), # $ tainted
|
||||
)
|
||||
|
||||
for v in tainted_dict.values():
|
||||
|
||||
Reference in New Issue
Block a user