@@ -8,6 +8,7 @@ private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPr
88private import codeql.typetracking.internal.SummaryTypeTracker as SummaryTypeTracker
99private import semmle.python.dataflow.new.internal.FlowSummaryImpl as FlowSummaryImpl
1010private import semmle.python.dataflow.new.internal.DataFlowDispatch as DataFlowDispatch
11+ private import semmle.python.dataflow.new.internal.IterableUnpacking as IterableUnpacking
1112
1213private module SummaryTypeTrackerInput implements SummaryTypeTracker:: Input {
1314 // Dataflow nodes
@@ -135,7 +136,27 @@ module TypeTrackingInput implements Shared::TypeTrackingInput {
135136 }
136137
137138 /** 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+ }
139160
140161 /** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */
141162 predicate levelStepCall ( Node nodeFrom , LocalSourceNode nodeTo ) { none ( ) }
@@ -200,7 +221,10 @@ module TypeTrackingInput implements Shared::TypeTrackingInput {
200221 nodeTo = storeTarget
201222 or
202223 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
204228 or
205229 TypeTrackerSummaryFlow:: basicStoreStep ( nodeFrom , nodeTo , content )
206230 }
@@ -216,7 +240,22 @@ module TypeTrackingInput implements Shared::TypeTrackingInput {
216240 nodeTo = a
217241 )
218242 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+ )
220259 or
221260 TypeTrackerSummaryFlow:: basicLoadStep ( nodeFrom , nodeTo , content )
222261 }
0 commit comments