Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dac2b57

Browse files
committed
Python: type-track through dict-updates
1 parent 73fe596 commit dac2b57

4 files changed

Lines changed: 16 additions & 4 deletions

File tree

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,8 @@ predicate storeStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
648648
tupleStoreStep(nodeFrom, c, nodeTo)
649649
or
650650
dictStoreStep(nodeFrom, c, nodeTo)
651+
or
652+
moreDictStoreSteps(nodeFrom, c, nodeTo)
651653
}
652654

653655
/**
@@ -661,8 +663,6 @@ predicate storeStep(Node nodeFrom, ContentSet c, Node nodeTo) {
661663
or
662664
setStoreStep(nodeFrom, c, nodeTo)
663665
or
664-
moreDictStoreSteps(nodeFrom, c, nodeTo)
665-
or
666666
comprehensionStoreStep(nodeFrom, c, nodeTo)
667667
or
668668
iterableUnpackingStoreStep(nodeFrom, c, nodeTo)

python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackingImpl.qll

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,18 @@ module TypeTrackingInput implements Shared::TypeTrackingInput {
175175
nodeTo = a.getObject()
176176
)
177177
or
178-
DataFlowPrivate::storeStepCommon(nodeFrom, content, nodeTo)
178+
// type-tracking doesn't really handle PostUpdateNodes, so for some assignment steps
179+
// like `my_dict["foo"] = foo` the data-flow step targets the PostUpdateNode for
180+
// `my_dict`, where we want to translate that into a type-tracking step that targets
181+
// the normal/non-PostUpdateNode for `my_dict`.
182+
exists(DataFlowPublic::Node storeTarget |
183+
DataFlowPrivate::storeStepCommon(nodeFrom, content, storeTarget)
184+
|
185+
not storeTarget instanceof DataFlowPrivate::SyntheticPostUpdateNode and
186+
nodeTo = storeTarget
187+
or
188+
nodeTo = storeTarget.(DataFlowPrivate::SyntheticPostUpdateNode).getPreUpdateNode()
189+
)
179190
or
180191
TypeTrackerSummaryFlow::basicStoreStep(nodeFrom, nodeTo, content)
181192
}

python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ typeTracker_found_pointsTo_notFound
3939
| code/class_super.py:108:1:108:8 | ControlFlowNode for Attribute() | Z.foo |
4040
| code/def_in_function.py:22:5:22:11 | ControlFlowNode for Attribute() | test.A.foo |
4141
| code/func_ref_in_content.py:29:1:29:4 | ControlFlowNode for f4() | func |
42+
| code/func_ref_in_content.py:40:1:40:4 | ControlFlowNode for f5() | func |
4243
| code/isinstance.py:9:13:9:22 | ControlFlowNode for Attribute() | A.foo |
4344
| code/isinstance.py:9:13:9:22 | ControlFlowNode for Attribute() | ASub.foo |
4445
| code/isinstance.py:14:13:14:22 | ControlFlowNode for Attribute() | A.foo |

python/ql/test/experimental/library-tests/CallGraph/code/func_ref_in_content.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def return_func_in_dict_update():
3737
dct2 = return_func_in_dict_update() # $ pt,tt=return_func_in_dict_update
3838

3939
f5 = dct2['func']
40-
f5() # $ MISSING: tt=func
40+
f5() # $ tt=func
4141

4242

4343
def return_func_in_list():

0 commit comments

Comments
 (0)