Merge pull request #1472 from markshannon/python-taint-through-iterators

Python: Track taint through iteration and iterators including generators.
This commit is contained in:
Taus 2019-06-19 11:33:10 +02:00 коммит произвёл GitHub
Родитель b43df7439e e8190d9a7b
Коммит cb43d27344
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 133 добавлений и 1 удалений

Просмотреть файл

@ -159,6 +159,12 @@ abstract class TaintKind extends string {
string repr() { result = this }
/** Gets the taint resulting from iterating over this kind of taint.
* For example iterating over a text file produces lines. So iterating
* over a tainted file would result in tainted strings
*/
TaintKind getTaintForIteration() { none() }
}
/** Taint kinds representing collections of other taint kind.
@ -212,6 +218,10 @@ class SequenceKind extends CollectionKind {
result = "sequence of " + itemKind
}
override TaintKind getTaintForIteration() {
result = itemKind
}
}
@ -863,6 +873,10 @@ library module TaintFlowImplementation {
or
call_taint_step(fromnode, totaint, tocontext, tonode)
or
iteration_step(fromnode, totaint, tocontext, tonode)
or
yield_step(fromnode, totaint, tocontext, tonode)
or
exists(DataFlowNode fromnodenode |
fromnodenode = fromnode.getNode() and
(
@ -1053,6 +1067,26 @@ library module TaintFlowImplementation {
)
}
predicate yield_step(TaintedNode fromnode, TrackedValue totaint, CallContext tocontext, CallNode call) {
exists(PyFunctionObject func |
func.getFunction().isGenerator() and
func.getACall() = call and
(
fromnode.getContext() = tocontext.getCallee(call)
or
fromnode.getContext() = tocontext and tocontext = TTop()
) and
exists(Yield yield |
yield.getScope() = func.getFunction() and
yield.getValue() = fromnode.getNode().getNode()
) and
exists(SequenceKind seq |
seq.getItem() = fromnode.getTaintKind() and
totaint = fromnode.getTrackedValue().toKind(seq)
)
)
}
predicate call_taint_step(TaintedNode fromnode, TrackedValue totaint, CallContext tocontext, CallNode call) {
exists(string name |
call.getFunction().(AttrNode).getObject(name) = fromnode.getNode() and
@ -1067,6 +1101,13 @@ library module TaintFlowImplementation {
)
}
/** Holds if `v` is defined by a `for` statement, the definition being `defn` */
cached predicate iteration_step(TaintedNode fromnode, TrackedValue totaint, CallContext tocontext, ControlFlowNode iter) {
exists(ForNode for | for.iterates(iter, fromnode.getNode())) and
totaint = TTrackedTaint(fromnode.getTaintKind().getTaintForIteration()) and
tocontext = fromnode.getContext()
}
predicate self_init_end_transfer(EssaVariable self, CallContext callee, CallNode call, CallContext caller) {
exists(ClassValue cls, Function init |
call.getFunction().pointsTo(cls) and
@ -1161,6 +1202,9 @@ library module TaintFlowImplementation {
tainted_with(def, context, origin)
or
tainted_exception_capture(def, context, origin)
or
tainted_iteration(def, context, origin)
}
predicate tainted_scope_entry(ScopeEntryDefinition def, CallContext context, TaintedNode origin) {
@ -1363,6 +1407,12 @@ library module TaintFlowImplementation {
context = fromnode.getContext()
}
pragma [noinline]
private predicate tainted_iteration(IterationDefinition def, CallContext context, TaintedNode fromnode) {
def.getDefiningNode() = fromnode.getNode() and
context = fromnode.getContext()
}
/* A call that returns a copy (or similar) of the argument */
predicate copyCall(ControlFlowNode fromnode, CallNode tonode) {
tonode.getFunction().(AttrNode).getObject("copy") = fromnode

Просмотреть файл

@ -362,7 +362,29 @@ class FalseySource extends TaintSource {
}
class TaintIterable extends TaintKind {
TaintIterable() {
this = "iterable.simple"
}
override TaintKind getTaintForIteration() {
result instanceof SimpleTest
}
}
class TaintIterableSource extends TaintSource {
TaintIterableSource() {
this.(NameNode).getId() = "ITERABLE_SOURCE"
}
override predicate isSourceOf(TaintKind kind) {
kind instanceof TaintIterable
}
}

Просмотреть файл

@ -180,3 +180,12 @@
| test.py:197 | Pi(t_0) [true] | test.py:195 | Taint simple.test | SOURCE |
| test.py:199 | ArgumentRefinement(t_3) | test.py:195 | Taint simple.test | SOURCE |
| test.py:199 | Pi(t_0) [false] | test.py:195 | Taint simple.test | SOURCE |
| test.py:202 | ITERABLE_SOURCE | test.py:202 | Taint iterable.simple | ITERABLE_SOURCE |
| test.py:203 | IterationDefinition | test.py:203 | Taint simple.test | i |
| test.py:203 | phi(i_0, i_2) | test.py:203 | Taint simple.test | i |
| test.py:208 | List | test.py:208 | Taint [simple.test] | List |
| test.py:209 | IterationDefinition | test.py:209 | Taint simple.test | i |
| test.py:209 | phi(i_0, i_2) | test.py:209 | Taint simple.test | i |
| test.py:213 | IterationDefinition | test.py:213 | Taint simple.test | x |
| test.py:213 | phi(x_2, x_3) | test.py:213 | Taint simple.test | x |
| test.py:214 | ArgumentRefinement(x_1) | test.py:213 | Taint simple.test | x |

Просмотреть файл

@ -67,6 +67,9 @@
| Taint [simple.test] | test.py:172 | x | |
| Taint [simple.test] | test.py:174 | l | |
| Taint [simple.test] | test.py:174 | list() | |
| Taint [simple.test] | test.py:208 | List | |
| Taint [simple.test] | test.py:209 | seq | |
| Taint [simple.test] | test.py:213 | flow_in_generator() | |
| Taint basic.custom | test.py:72 | arg | test.py:121 |
| Taint basic.custom | test.py:73 | arg | test.py:121 |
| Taint basic.custom | test.py:120 | CUSTOM_SOURCE | |
@ -96,6 +99,8 @@
| Taint explicit.carrier | carrier.py:35 | x | |
| Taint falsey | test.py:189 | FALSEY | |
| Taint falsey | test.py:190 | t | |
| Taint iterable.simple | test.py:202 | ITERABLE_SOURCE | |
| Taint iterable.simple | test.py:203 | t | |
| Taint paper | rockpaperscissors.py:6 | arg | rockpaperscissors.py:32 |
| Taint paper | rockpaperscissors.py:9 | arg | rockpaperscissors.py:26 |
| Taint paper | rockpaperscissors.py:25 | Attribute() | |
@ -226,6 +231,14 @@
| Taint simple.test | test.py:196 | t | |
| Taint simple.test | test.py:197 | t | |
| Taint simple.test | test.py:199 | t | |
| Taint simple.test | test.py:203 | i | |
| Taint simple.test | test.py:204 | i | |
| Taint simple.test | test.py:205 | i | |
| Taint simple.test | test.py:208 | SOURCE | |
| Taint simple.test | test.py:209 | i | |
| Taint simple.test | test.py:210 | i | |
| Taint simple.test | test.py:213 | x | |
| Taint simple.test | test.py:214 | x | |
| Taint {simple.test} | test.py:169 | Dict | |
| Taint {simple.test} | test.py:171 | d | |
| Taint {simple.test} | test.py:173 | y | |

Просмотреть файл

@ -36,3 +36,4 @@
| simple.test | test.py:178 | 186 | t | simple.test |
| simple.test | test.py:195 | 197 | t | simple.test |
| simple.test | test.py:195 | 199 | t | simple.test |
| simple.test | test.py:208 | 214 | x | simple.test |

Просмотреть файл

@ -43,3 +43,5 @@
| test.py:178 | SOURCE | simple.test |
| test.py:189 | FALSEY | falsey |
| test.py:195 | SOURCE | simple.test |
| test.py:202 | ITERABLE_SOURCE | iterable.simple |
| test.py:208 | SOURCE | simple.test |

Просмотреть файл

@ -59,6 +59,9 @@
| Taint [simple.test] | test.py:170 | l | | --> | Taint [simple.test] | test.py:172 | x | |
| Taint [simple.test] | test.py:172 | x | | --> | Taint simple.test | test.py:172 | Subscript | |
| Taint [simple.test] | test.py:174 | l | | --> | Taint [simple.test] | test.py:174 | list() | |
| Taint [simple.test] | test.py:208 | List | | --> | Taint [simple.test] | test.py:209 | seq | |
| Taint [simple.test] | test.py:209 | seq | | --> | Taint simple.test | test.py:209 | i | |
| Taint [simple.test] | test.py:213 | flow_in_generator() | | --> | Taint simple.test | test.py:213 | x | |
| Taint basic.custom | test.py:72 | arg | test.py:121 | --> | Taint basic.custom | test.py:73 | arg | test.py:121 |
| Taint basic.custom | test.py:73 | arg | test.py:121 | --> | Taint basic.custom | test.py:121 | hub() | |
| Taint basic.custom | test.py:120 | CUSTOM_SOURCE | | --> | Taint basic.custom | test.py:121 | t | |
@ -83,6 +86,8 @@
| Taint explicit.carrier | carrier.py:34 | Attribute | | --> | Taint explicit.carrier | carrier.py:35 | x | |
| Taint explicit.carrier | carrier.py:35 | x | | --> | Taint simple.test | carrier.py:35 | Attribute() | |
| Taint falsey | test.py:189 | FALSEY | | --> | Taint falsey | test.py:190 | t | |
| Taint iterable.simple | test.py:202 | ITERABLE_SOURCE | | --> | Taint iterable.simple | test.py:203 | t | |
| Taint iterable.simple | test.py:203 | t | | --> | Taint simple.test | test.py:203 | i | |
| Taint paper | rockpaperscissors.py:25 | Attribute() | | --> | Taint paper | rockpaperscissors.py:26 | y | |
| Taint paper | rockpaperscissors.py:26 | y | | --> | Taint paper | rockpaperscissors.py:9 | arg | rockpaperscissors.py:26 |
| Taint paper | rockpaperscissors.py:30 | Attribute() | | --> | Taint paper | rockpaperscissors.py:32 | y | |
@ -181,6 +186,12 @@
| Taint simple.test | test.py:195 | SOURCE | | --> | Taint simple.test | test.py:196 | t | |
| Taint simple.test | test.py:195 | SOURCE | | --> | Taint simple.test | test.py:197 | t | |
| Taint simple.test | test.py:195 | SOURCE | | --> | Taint simple.test | test.py:199 | t | |
| Taint simple.test | test.py:203 | i | | --> | Taint simple.test | test.py:204 | i | |
| Taint simple.test | test.py:203 | i | | --> | Taint simple.test | test.py:205 | i | |
| Taint simple.test | test.py:208 | SOURCE | | --> | Taint [simple.test] | test.py:208 | List | |
| Taint simple.test | test.py:209 | i | | --> | Taint simple.test | test.py:210 | i | |
| Taint simple.test | test.py:210 | i | | --> | Taint [simple.test] | test.py:213 | flow_in_generator() | |
| Taint simple.test | test.py:213 | x | | --> | Taint simple.test | test.py:214 | x | |
| Taint {simple.test} | test.py:169 | Dict | | --> | Taint {simple.test} | test.py:171 | d | |
| Taint {simple.test} | test.py:169 | Dict | | --> | Taint {simple.test} | test.py:175 | d | |
| Taint {simple.test} | test.py:171 | d | | --> | Taint {simple.test} | test.py:173 | y | |

Просмотреть файл

@ -182,3 +182,12 @@
| test.py:197 | t_2 | test.py:195 | Taint simple.test | SOURCE |
| test.py:199 | t_3 | test.py:195 | Taint simple.test | SOURCE |
| test.py:199 | t_4 | test.py:195 | Taint simple.test | SOURCE |
| test.py:202 | t_0 | test.py:202 | Taint iterable.simple | ITERABLE_SOURCE |
| test.py:203 | i_1 | test.py:203 | Taint simple.test | i |
| test.py:203 | i_2 | test.py:203 | Taint simple.test | i |
| test.py:208 | seq_0 | test.py:208 | Taint [simple.test] | List |
| test.py:209 | i_1 | test.py:209 | Taint simple.test | i |
| test.py:209 | i_2 | test.py:209 | Taint simple.test | i |
| test.py:213 | x_0 | test.py:213 | Taint simple.test | x |
| test.py:213 | x_1 | test.py:213 | Taint simple.test | x |
| test.py:214 | x_2 | test.py:213 | Taint simple.test | x |

Просмотреть файл

@ -198,3 +198,18 @@ def flow_through_type_test_if_no_class():
else:
SINK(t)
def flow_in_iteration():
t = ITERABLE_SOURCE
for i in t:
i
return i
def flow_in_generator():
seq = [SOURCE]
for i in seq:
yield i
def flow_from_generator():
for x in flow_in_generator():
SINK(x)