@@ -688,17 +688,38 @@ predicate tupleStoreStep(CfgNode nodeFrom, TupleElementContent c, CfgNode nodeTo
688
688
}
689
689
690
690
/** Data flows from an element of a dictionary to the dictionary at a specific key. */
691
- predicate dictStoreStep ( CfgNode nodeFrom , DictionaryElementContent c , CfgNode nodeTo ) {
691
+ predicate dictStoreStep ( CfgNode nodeFrom , DictionaryElementContent c , Node nodeTo ) {
692
692
// Dictionary
693
693
// `{..., "key" = 42, ...}`
694
694
// nodeFrom is `42`, cfg node
695
695
// nodeTo is the dict, `{..., "key" = 42, ...}`, cfg node
696
696
// c denotes element of dictionary and the key `"key"`
697
697
exists ( KeyValuePair item |
698
- item = nodeTo .getNode ( ) .( DictNode ) .getNode ( ) .( Dict ) .getAnItem ( ) and
698
+ item = nodeTo .asCfgNode ( ) .( DictNode ) .getNode ( ) .( Dict ) .getAnItem ( ) and
699
699
nodeFrom .getNode ( ) .getNode ( ) = item .getValue ( ) and
700
700
c .getKey ( ) = item .getKey ( ) .( StrConst ) .getS ( )
701
701
)
702
+ or
703
+ exists ( SubscriptNode subscript |
704
+ nodeTo .( PostUpdateNode ) .getPreUpdateNode ( ) .asCfgNode ( ) = subscript .getObject ( ) and
705
+ nodeFrom .asCfgNode ( ) = subscript .( DefinitionNode ) .getValue ( ) and
706
+ c .getKey ( ) = subscript .getIndex ( ) .getNode ( ) .( StrConst ) .getText ( )
707
+ )
708
+ or
709
+ // see https://docs.python.org/3.10/library/stdtypes.html#dict.setdefault
710
+ exists ( MethodCallNode call |
711
+ call .calls ( nodeTo .( PostUpdateNode ) .getPreUpdateNode ( ) , [ "setdefault" ] ) and
712
+ call .getArg ( 0 ) .asExpr ( ) .( StrConst ) .getText ( ) = c .( DictionaryElementContent ) .getKey ( ) and
713
+ nodeFrom = call .getArg ( 1 )
714
+ )
715
+ }
716
+
717
+ predicate dictClearStep ( Node node , DictionaryElementContent c ) {
718
+ exists ( SubscriptNode subscript |
719
+ subscript instanceof DefinitionNode and
720
+ node .asCfgNode ( ) = subscript .getObject ( ) and
721
+ c .getKey ( ) = subscript .getIndex ( ) .getNode ( ) .( StrConst ) .getText ( )
722
+ )
702
723
}
703
724
704
725
/** Data flows from an element expression in a comprehension to the comprehension. */
@@ -761,6 +782,8 @@ predicate defaultValueFlowStep(CfgNode nodeFrom, CfgNode nodeTo) {
761
782
predicate readStep ( Node nodeFrom , Content c , Node nodeTo ) {
762
783
subscriptReadStep ( nodeFrom , c , nodeTo )
763
784
or
785
+ dictReadStep ( nodeFrom , c , nodeTo )
786
+ or
764
787
iterableUnpackingReadStep ( nodeFrom , c , nodeTo )
765
788
or
766
789
matchReadStep ( nodeFrom , c , nodeTo )
@@ -799,6 +822,17 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
799
822
)
800
823
}
801
824
825
+ predicate dictReadStep ( CfgNode nodeFrom , Content c , CfgNode nodeTo ) {
826
+ // see
827
+ // - https://docs.python.org/3.10/library/stdtypes.html#dict.get
828
+ // - https://docs.python.org/3.10/library/stdtypes.html#dict.setdefault
829
+ exists ( MethodCallNode call |
830
+ call .calls ( nodeFrom , [ "get" , "setdefault" ] ) and
831
+ call .getArg ( 0 ) .asExpr ( ) .( StrConst ) .getText ( ) = c .( DictionaryElementContent ) .getKey ( ) and
832
+ nodeTo = call
833
+ )
834
+ }
835
+
802
836
/** Data flows from a sequence to a call to `pop` on the sequence. */
803
837
predicate popReadStep ( CfgNode nodeFrom , Content c , CfgNode nodeTo ) {
804
838
// set.pop or list.pop
@@ -873,6 +907,8 @@ predicate clearsContent(Node n, Content c) {
873
907
or
874
908
attributeClearStep ( n , c )
875
909
or
910
+ dictClearStep ( n , c )
911
+ or
876
912
FlowSummaryImpl:: Private:: Steps:: summaryClearsContent ( n , c )
877
913
or
878
914
dictSplatParameterNodeClearStep ( n , c )
0 commit comments