@@ -8,6 +8,7 @@ private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPr
8
8
private import codeql.typetracking.internal.SummaryTypeTracker as SummaryTypeTracker
9
9
private import semmle.python.dataflow.new.internal.FlowSummaryImpl as FlowSummaryImpl
10
10
private import semmle.python.dataflow.new.internal.DataFlowDispatch as DataFlowDispatch
11
+ private import semmle.python.dataflow.new.internal.IterableUnpacking as IterableUnpacking
11
12
12
13
private module SummaryTypeTrackerInput implements SummaryTypeTracker:: Input {
13
14
// Dataflow nodes
@@ -135,7 +136,27 @@ module TypeTrackingInput implements Shared::TypeTrackingInput {
135
136
}
136
137
137
138
/** Holds if there is a simple local flow step from `nodeFrom` to `nodeTo` */
138
- predicate simpleLocalSmallStep = DataFlowPrivate:: simpleLocalFlowStepForTypetracking / 2 ;
139
+ predicate simpleLocalSmallStep ( Node nodeFrom , Node nodeTo ) {
140
+ DataFlowPrivate:: simpleLocalFlowStepForTypetracking ( nodeFrom , nodeTo ) and
141
+ // for `for k,v in foo` no need to do local flow step from the synthetic sequence
142
+ // node for `k,v` to the tuple `k,v` -- since type-tracking only supports one level
143
+ // of content tracking, and there is one read-step from `foo` the synthetic sequence
144
+ // node required, we can skip the flow step from the synthetic sequence node to the
145
+ // tuple itself, since the read-step from the tuple to the tuple elements will not
146
+ // matter.
147
+ not (
148
+ IterableUnpacking:: iterableUnpackingForReadStep ( _, _, nodeFrom ) and
149
+ IterableUnpacking:: iterableUnpackingTupleFlowStep ( nodeFrom , nodeTo )
150
+ ) and
151
+ // for nested iterable unpacking, such as `[[a]] = foo` or `((a,b),) = bar`, we can
152
+ // ignore the flow steps from the synthetic sequence node to the real sequence node,
153
+ // since we only support one level of content in type-trackers, and the nested
154
+ // structure requires two levels at least to be useful.
155
+ not exists ( SequenceNode outer |
156
+ outer .getAnElement ( ) = nodeTo .asCfgNode ( ) and
157
+ IterableUnpacking:: iterableUnpackingTupleFlowStep ( nodeFrom , nodeTo )
158
+ )
159
+ }
139
160
140
161
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */
141
162
predicate levelStepCall ( Node nodeFrom , LocalSourceNode nodeTo ) { none ( ) }
@@ -200,7 +221,10 @@ module TypeTrackingInput implements Shared::TypeTrackingInput {
200
221
nodeTo = storeTarget
201
222
or
202
223
nodeTo = storeTarget .( DataFlowPrivate:: SyntheticPostUpdateNode ) .getPreUpdateNode ( )
203
- )
224
+ ) and
225
+ // when only supporting precise content, no need for IterableElementNode (since it
226
+ // is only fed set/list content)
227
+ not nodeFrom instanceof DataFlowPublic:: IterableElementNode
204
228
or
205
229
TypeTrackerSummaryFlow:: basicStoreStep ( nodeFrom , nodeTo , content )
206
230
}
@@ -216,7 +240,22 @@ module TypeTrackingInput implements Shared::TypeTrackingInput {
216
240
nodeTo = a
217
241
)
218
242
or
219
- DataFlowPrivate:: readStepCommon ( nodeFrom , content , nodeTo )
243
+ DataFlowPrivate:: readStepCommon ( nodeFrom , content , nodeTo ) and
244
+ // Since we only support one level of content in type-trackers we don't actually
245
+ // support `(aa, ab), (ba, bb) = ...`. Therefore we exclude the read-step from `(aa,
246
+ // ab)` to `aa` (since it is not needed).
247
+ not exists ( SequenceNode outer |
248
+ outer .getAnElement ( ) = nodeFrom .asCfgNode ( ) and
249
+ IterableUnpacking:: iterableUnpackingTupleFlowStep ( _, nodeFrom )
250
+ ) and
251
+ // Again, due to only supporting one level deep, for `for (k,v) in ...` we exclude read-step from
252
+ // the tuple to `k` and `v`.
253
+ not exists ( DataFlowPublic:: IterableSequenceNode seq , DataFlowPublic:: IterableElementNode elem |
254
+ IterableUnpacking:: iterableUnpackingForReadStep ( _, _, seq ) and
255
+ IterableUnpacking:: iterableUnpackingConvertingReadStep ( seq , _, elem ) and
256
+ IterableUnpacking:: iterableUnpackingConvertingStoreStep ( elem , _, nodeFrom ) and
257
+ nodeFrom .asCfgNode ( ) instanceof SequenceNode
258
+ )
220
259
or
221
260
TypeTrackerSummaryFlow:: basicLoadStep ( nodeFrom , nodeTo , content )
222
261
}
0 commit comments