@@ -159,6 +159,12 @@ abstract class TaintKind extends string {
159159
160160 string repr ( ) { result = this }
161161
162+ /** Gets the taint resulting from iterating over this kind of taint.
163+ * For example iterating over a text file produces lines. So iterating
164+ * over a tainted file would result in tainted strings
165+ */
166+ TaintKind getTaintForIteration ( ) { none ( ) }
167+
162168}
163169
164170/** Taint kinds representing collections of other taint kind.
@@ -212,6 +218,10 @@ class SequenceKind extends CollectionKind {
212218 result = "sequence of " + itemKind
213219 }
214220
221+ override TaintKind getTaintForIteration ( ) {
222+ result = itemKind
223+ }
224+
215225}
216226
217227
@@ -863,6 +873,10 @@ library module TaintFlowImplementation {
863873 or
864874 call_taint_step ( fromnode , totaint , tocontext , tonode )
865875 or
876+ iteration_step ( fromnode , totaint , tocontext , tonode )
877+ or
878+ yield_step ( fromnode , totaint , tocontext , tonode )
879+ or
866880 exists ( DataFlowNode fromnodenode |
867881 fromnodenode = fromnode .getNode ( ) and
868882 (
@@ -1053,6 +1067,26 @@ library module TaintFlowImplementation {
10531067 )
10541068 }
10551069
1070+ predicate yield_step ( TaintedNode fromnode , TrackedValue totaint , CallContext tocontext , CallNode call ) {
1071+ exists ( PyFunctionObject func |
1072+ func .getFunction ( ) .isGenerator ( ) and
1073+ func .getACall ( ) = call and
1074+ (
1075+ fromnode .getContext ( ) = tocontext .getCallee ( call )
1076+ or
1077+ fromnode .getContext ( ) = tocontext and tocontext = TTop ( )
1078+ ) and
1079+ exists ( Yield yield |
1080+ yield .getScope ( ) = func .getFunction ( ) and
1081+ yield .getValue ( ) = fromnode .getNode ( ) .getNode ( )
1082+ ) and
1083+ exists ( SequenceKind seq |
1084+ seq .getItem ( ) = fromnode .getTaintKind ( ) and
1085+ totaint = fromnode .getTrackedValue ( ) .toKind ( seq )
1086+ )
1087+ )
1088+ }
1089+
10561090 predicate call_taint_step ( TaintedNode fromnode , TrackedValue totaint , CallContext tocontext , CallNode call ) {
10571091 exists ( string name |
10581092 call .getFunction ( ) .( AttrNode ) .getObject ( name ) = fromnode .getNode ( ) and
@@ -1067,6 +1101,13 @@ library module TaintFlowImplementation {
10671101 )
10681102 }
10691103
1104+ /** Holds if `v` is defined by a `for` statement, the definition being `defn` */
1105+ cached predicate iteration_step ( TaintedNode fromnode , TrackedValue totaint , CallContext tocontext , ControlFlowNode iter ) {
1106+ exists ( ForNode for | for .iterates ( iter , fromnode .getNode ( ) ) ) and
1107+ totaint = TTrackedTaint ( fromnode .getTaintKind ( ) .getTaintForIteration ( ) ) and
1108+ tocontext = fromnode .getContext ( )
1109+ }
1110+
10701111 predicate self_init_end_transfer ( EssaVariable self , CallContext callee , CallNode call , CallContext caller ) {
10711112 exists ( ClassValue cls , Function init |
10721113 call .getFunction ( ) .pointsTo ( cls ) and
@@ -1161,6 +1202,9 @@ library module TaintFlowImplementation {
11611202 tainted_with ( def , context , origin )
11621203 or
11631204 tainted_exception_capture ( def , context , origin )
1205+ or
1206+ tainted_iteration ( def , context , origin )
1207+
11641208 }
11651209
11661210 predicate tainted_scope_entry ( ScopeEntryDefinition def , CallContext context , TaintedNode origin ) {
@@ -1363,6 +1407,12 @@ library module TaintFlowImplementation {
13631407 context = fromnode .getContext ( )
13641408 }
13651409
1410+ pragma [ noinline]
1411+ private predicate tainted_iteration ( IterationDefinition def , CallContext context , TaintedNode fromnode ) {
1412+ def .getDefiningNode ( ) = fromnode .getNode ( ) and
1413+ context = fromnode .getContext ( )
1414+ }
1415+
13661416 /* A call that returns a copy (or similar) of the argument */
13671417 predicate copyCall ( ControlFlowNode fromnode , CallNode tonode ) {
13681418 tonode .getFunction ( ) .( AttrNode ) .getObject ( "copy" ) = fromnode
0 commit comments