@@ -9,6 +9,7 @@ private import codeql.swift.dataflow.FlowSummary as FlowSummary
9
9
private import codeql.swift.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
10
10
private import codeql.swift.frameworks.StandardLibrary.PointerTypes
11
11
private import codeql.swift.frameworks.StandardLibrary.Array
12
+ private import codeql.swift.frameworks.StandardLibrary.Dictionary
12
13
13
14
/** Gets the callable in which this node occurs. */
14
15
DataFlowCallable nodeGetEnclosingCallable ( Node n ) { result = n .( NodeImpl ) .getEnclosingCallable ( ) }
@@ -114,6 +115,9 @@ private module Cached {
114
115
any ( ApplyExpr apply ) .getQualifier ( ) , any ( TupleElementExpr te ) .getSubExpr ( ) ,
115
116
any ( SubscriptExpr se ) .getBase ( )
116
117
] )
118
+ } or
119
+ TDictionarySubscriptNode ( SubscriptExpr e ) {
120
+ e .getBase ( ) .getType ( ) .getCanonicalType ( ) instanceof CanonicalDictionaryType
117
121
}
118
122
119
123
private predicate localSsaFlowStepUseUse ( Ssa:: Definition def , Node nodeFrom , Node nodeTo ) {
@@ -296,6 +300,28 @@ import Cached
296
300
/** Holds if `n` should be hidden from path explanations. */
297
301
predicate nodeIsHidden ( Node n ) { n instanceof FlowSummaryNode }
298
302
303
+ /**
304
+ * The intermediate node for a dictionary subscript operation `dict[key]`. In a write, this is used
305
+ * as the destination of the `storeStep`s that add `TupleContent`s and the source of the storeStep
306
+ * that adds `CollectionContent`. In a read, this is the destination of the `readStep` that pops
307
+ * `CollectionContent` and the source of the `readStep` that pops `TupleContent[0]`
308
+ */
309
+ private class DictionarySubscriptNode extends NodeImpl , TDictionarySubscriptNode {
310
+ SubscriptExpr expr ;
311
+
312
+ DictionarySubscriptNode ( ) { this = TDictionarySubscriptNode ( expr ) }
313
+
314
+ override DataFlowCallable getEnclosingCallable ( ) {
315
+ result .asSourceCallable ( ) = expr .getEnclosingCallable ( )
316
+ }
317
+
318
+ override string toStringImpl ( ) { result = "DictionarySubscriptNode" }
319
+
320
+ override Location getLocationImpl ( ) { result = expr .getLocation ( ) }
321
+
322
+ SubscriptExpr getExpr ( ) { result = expr }
323
+ }
324
+
299
325
private module ParameterNodes {
300
326
abstract class ParameterNodeImpl extends NodeImpl {
301
327
predicate isParameterOf ( DataFlowCallable c , ParameterPosition pos ) { none ( ) }
@@ -735,6 +761,32 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
735
761
c instanceof OptionalSomeContentSet
736
762
)
737
763
or
764
+ // assignment to a dictionary value via subscript operator, with intermediate step
765
+ // `dict[key] = value`
766
+ exists ( AssignExpr assign , SubscriptExpr subscript |
767
+ subscript = assign .getDest ( ) and
768
+ (
769
+ subscript .getArgument ( 0 ) .getExpr ( ) = node1 .asExpr ( ) and
770
+ node2 .( DictionarySubscriptNode ) .getExpr ( ) = subscript and
771
+ c .isSingleton ( any ( Content:: TupleContent tc | tc .getIndex ( ) = 0 ) )
772
+ or
773
+ assign .getSource ( ) = node1 .asExpr ( ) and
774
+ node2 .( DictionarySubscriptNode ) .getExpr ( ) = subscript and
775
+ c .isSingleton ( any ( Content:: TupleContent tc | tc .getIndex ( ) = 1 ) )
776
+ or
777
+ node1 .( DictionarySubscriptNode ) .getExpr ( ) = subscript and
778
+ node2 .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = subscript .getBase ( ) and
779
+ c .isSingleton ( any ( Content:: CollectionContent cc ) )
780
+ )
781
+ )
782
+ or
783
+ // creation of a dictionary `[key: value, ...]`
784
+ exists ( DictionaryExpr dict |
785
+ node1 .asExpr ( ) = dict .getAnElement ( ) and
786
+ node2 .asExpr ( ) = dict and
787
+ c .isSingleton ( any ( Content:: CollectionContent cc ) )
788
+ )
789
+ or
738
790
FlowSummaryImpl:: Private:: Steps:: summaryStoreStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
739
791
node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
740
792
}
@@ -826,6 +878,17 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
826
878
)
827
879
)
828
880
or
881
+ // read of a dictionary value via subscript operator
882
+ exists ( SubscriptExpr subscript |
883
+ subscript .getBase ( ) = node1 .asExpr ( ) and
884
+ node2 .( DictionarySubscriptNode ) .getExpr ( ) = subscript and
885
+ c .isSingleton ( any ( Content:: CollectionContent cc ) )
886
+ or
887
+ subscript = node2 .asExpr ( ) and
888
+ node1 .( DictionarySubscriptNode ) .getExpr ( ) = subscript and
889
+ c .isSingleton ( any ( Content:: TupleContent tc | tc .getIndex ( ) = 1 ) )
890
+ )
891
+ or
829
892
FlowSummaryImpl:: Private:: Steps:: summaryReadStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
830
893
node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
831
894
}
@@ -836,7 +899,12 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
836
899
* in `x.f = newValue`.
837
900
*/
838
901
predicate clearsContent ( Node n , ContentSet c ) {
839
- n = any ( PostUpdateNode pun | storeStep ( _, c , pun ) ) .getPreUpdateNode ( )
902
+ n = any ( PostUpdateNode pun | storeStep ( _, c , pun ) ) .getPreUpdateNode ( ) and
903
+ (
904
+ c .isSingleton ( any ( Content:: FieldContent fc ) ) or
905
+ c .isSingleton ( any ( Content:: TupleContent tc ) ) or
906
+ c .isSingleton ( any ( Content:: EnumContent ec ) )
907
+ )
840
908
}
841
909
842
910
/**
0 commit comments