@@ -688,17 +688,38 @@ predicate tupleStoreStep(CfgNode nodeFrom, TupleElementContent c, CfgNode nodeTo
688688}
689689
690690/** 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 ) {
692692 // Dictionary
693693 // `{..., "key" = 42, ...}`
694694 // nodeFrom is `42`, cfg node
695695 // nodeTo is the dict, `{..., "key" = 42, ...}`, cfg node
696696 // c denotes element of dictionary and the key `"key"`
697697 exists ( KeyValuePair item |
698- item = nodeTo .getNode ( ) .( DictNode ) .getNode ( ) .( Dict ) .getAnItem ( ) and
698+ item = nodeTo .asCfgNode ( ) .( DictNode ) .getNode ( ) .( Dict ) .getAnItem ( ) and
699699 nodeFrom .getNode ( ) .getNode ( ) = item .getValue ( ) and
700700 c .getKey ( ) = item .getKey ( ) .( StrConst ) .getS ( )
701701 )
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+ )
702723}
703724
704725/** Data flows from an element expression in a comprehension to the comprehension. */
@@ -761,6 +782,8 @@ predicate defaultValueFlowStep(CfgNode nodeFrom, CfgNode nodeTo) {
761782predicate readStep ( Node nodeFrom , Content c , Node nodeTo ) {
762783 subscriptReadStep ( nodeFrom , c , nodeTo )
763784 or
785+ dictReadStep ( nodeFrom , c , nodeTo )
786+ or
764787 iterableUnpackingReadStep ( nodeFrom , c , nodeTo )
765788 or
766789 matchReadStep ( nodeFrom , c , nodeTo )
@@ -799,6 +822,17 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
799822 )
800823}
801824
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+
802836/** Data flows from a sequence to a call to `pop` on the sequence. */
803837predicate popReadStep ( CfgNode nodeFrom , Content c , CfgNode nodeTo ) {
804838 // set.pop or list.pop
@@ -873,6 +907,8 @@ predicate clearsContent(Node n, Content c) {
873907 or
874908 attributeClearStep ( n , c )
875909 or
910+ dictClearStep ( n , c )
911+ or
876912 FlowSummaryImpl:: Private:: Steps:: summaryClearsContent ( n , c )
877913 or
878914 dictSplatParameterNodeClearStep ( n , c )
0 commit comments