diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll b/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll index 735a7e831bd..38ec4d146a4 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll @@ -87,8 +87,14 @@ module ImportResolution { ) { // to handle definitions guarded by if-then-else defFrom = defTo.(SsaImpl::PhiFunction).getAnInput() + or + // to handle uncertain writes such as `from X import *`, which create an + // uncertain SSA definition for every name in the importing scope. The + // immediately preceding definition is still potentially the value of the + // module export. + SsaImpl::Ssa::uncertainWriteDefinitionInput(defTo, defFrom) // Note: legacy ESSA refinement-step (e.g. for `foo.bar = X`) is - // not modelled in the new SSA. We rely on phi steps only. + // not modelled in the new SSA beyond the cases handled above. } /** diff --git a/python/ql/test/2/library-tests/comprehensions/ConsistencyCheck.ql b/python/ql/test/2/library-tests/comprehensions/ConsistencyCheck.ql index 2f5191fb547..c1a214e40c7 100644 --- a/python/ql/test/2/library-tests/comprehensions/ConsistencyCheck.ql +++ b/python/ql/test/2/library-tests/comprehensions/ConsistencyCheck.ql @@ -5,5 +5,7 @@ import python select count(Comprehension c | - count(c.toString()) != 1 or count(c.getLocation()) != 1 or not exists(c.getAFlowNode()) + count(c.toString()) != 1 or + count(c.getLocation()) != 1 or + not exists(ControlFlowNode n | n.getNode() = c) ) diff --git a/python/ql/test/experimental/import-resolution/ModuleExport.expected b/python/ql/test/experimental/import-resolution/ModuleExport.expected index f67ae004011..80605a523c0 100644 --- a/python/ql/test/experimental/import-resolution/ModuleExport.expected +++ b/python/ql/test/experimental/import-resolution/ModuleExport.expected @@ -1,120 +1,120 @@ -| attr_clash.__init__ | __file__ | attr_clash/__init__.py:6:6:6:13 | ControlFlowNode for __file__ | -| attr_clash.__init__ | clashing_attr | attr_clash/__init__.py:4:1:4:13 | ControlFlowNode for clashing_attr | -| attr_clash.__init__ | enter | attr_clash/__init__.py:2:1:2:5 | ControlFlowNode for enter | -| attr_clash.__init__ | exit | attr_clash/__init__.py:6:1:6:4 | ControlFlowNode for exit | -| attr_clash.clashing_attr | __file__ | attr_clash/clashing_attr.py:4:6:4:13 | ControlFlowNode for __file__ | -| attr_clash.clashing_attr | enter | attr_clash/clashing_attr.py:2:1:2:5 | ControlFlowNode for enter | -| attr_clash.clashing_attr | exit | attr_clash/clashing_attr.py:4:1:4:4 | ControlFlowNode for exit | -| attr_clash.non_clashing_submodule | __file__ | attr_clash/non_clashing_submodule.py:4:6:4:13 | ControlFlowNode for __file__ | -| attr_clash.non_clashing_submodule | enter | attr_clash/non_clashing_submodule.py:2:1:2:5 | ControlFlowNode for enter | -| attr_clash.non_clashing_submodule | exit | attr_clash/non_clashing_submodule.py:4:1:4:4 | ControlFlowNode for exit | -| bar | __file__ | bar.py:6:6:6:13 | ControlFlowNode for __file__ | -| bar | bar_attr | bar.py:4:1:4:8 | ControlFlowNode for bar_attr | -| bar | enter | bar.py:2:1:2:5 | ControlFlowNode for enter | -| bar | exit | bar.py:6:1:6:4 | ControlFlowNode for exit | -| baz | __file__ | baz.py:6:6:6:13 | ControlFlowNode for __file__ | -| baz | baz_attr | baz.py:4:1:4:8 | ControlFlowNode for baz_attr | -| baz | enter | baz.py:2:1:2:5 | ControlFlowNode for enter | -| baz | exit | baz.py:6:1:6:4 | ControlFlowNode for exit | -| block_flow_check | SOURCE | block_flow_check.py:12:25:12:30 | ControlFlowNode for SOURCE | -| block_flow_check | __file__ | block_flow_check.py:14:6:14:13 | ControlFlowNode for __file__ | -| block_flow_check | check | block_flow_check.py:12:1:12:5 | ControlFlowNode for check | -| block_flow_check | enter | block_flow_check.py:2:1:2:5 | ControlFlowNode for enter | -| block_flow_check | exit | block_flow_check.py:14:1:14:4 | ControlFlowNode for exit | -| block_flow_check | globals | block_flow_check.py:12:33:12:39 | ControlFlowNode for globals | -| block_flow_check | object | block_flow_check.py:4:14:4:19 | ControlFlowNode for object | -| foo | __file__ | foo.py:14:6:14:13 | ControlFlowNode for __file__ | -| foo | __private_foo_attr | foo.py:8:1:8:18 | ControlFlowNode for __private_foo_attr | -| foo | bar_reexported | foo.py:11:8:11:10 | ControlFlowNode for ImportExpr | -| foo | bar_reexported | foo.py:12:34:12:47 | ControlFlowNode for bar_reexported | -| foo | check | foo.py:12:1:12:5 | ControlFlowNode for check | -| foo | enter | foo.py:2:1:2:5 | ControlFlowNode for enter | -| foo | exit | foo.py:14:1:14:4 | ControlFlowNode for exit | -| foo | foo_attr | foo.py:5:1:5:8 | ControlFlowNode for foo_attr | -| foo | globals | foo.py:12:71:12:77 | ControlFlowNode for globals | -| generous_export | Exception | generous_export.py:16:11:16:19 | ControlFlowNode for Exception | -| generous_export | SOURCE | generous_export.py:15:11:15:16 | ControlFlowNode for SOURCE | -| generous_export | SOURCE | generous_export.py:20:25:20:30 | ControlFlowNode for SOURCE | -| generous_export | __file__ | generous_export.py:22:6:22:13 | ControlFlowNode for __file__ | -| generous_export | check | generous_export.py:20:1:20:5 | ControlFlowNode for check | -| generous_export | enter | generous_export.py:2:1:2:5 | ControlFlowNode for enter | -| generous_export | eval | generous_export.py:10:4:10:7 | ControlFlowNode for eval | -| generous_export | exit | generous_export.py:22:1:22:4 | ControlFlowNode for exit | -| generous_export | globals | generous_export.py:20:33:20:39 | ControlFlowNode for globals | -| generous_export | object | generous_export.py:4:14:4:19 | ControlFlowNode for object | -| generous_export | print | generous_export.py:15:5:15:9 | ControlFlowNode for print | -| has_defined_all | __all__ | has_defined_all.py:7:1:7:7 | ControlFlowNode for __all__ | -| has_defined_all | __file__ | has_defined_all.py:9:6:9:13 | ControlFlowNode for __file__ | -| has_defined_all | all_defined_bar | has_defined_all.py:5:1:5:15 | ControlFlowNode for all_defined_bar | -| has_defined_all | all_defined_foo | has_defined_all.py:4:1:4:15 | ControlFlowNode for all_defined_foo | -| has_defined_all | enter | has_defined_all.py:2:1:2:5 | ControlFlowNode for enter | -| has_defined_all | exit | has_defined_all.py:9:1:9:4 | ControlFlowNode for exit | -| has_defined_all_copy | __all__ | has_defined_all_copy.py:9:1:9:7 | ControlFlowNode for __all__ | -| has_defined_all_copy | __file__ | has_defined_all_copy.py:11:6:11:13 | ControlFlowNode for __file__ | -| has_defined_all_copy | all_defined_bar_copy | has_defined_all_copy.py:7:1:7:20 | ControlFlowNode for all_defined_bar_copy | -| has_defined_all_copy | all_defined_foo_copy | has_defined_all_copy.py:6:1:6:20 | ControlFlowNode for all_defined_foo_copy | -| has_defined_all_copy | enter | has_defined_all_copy.py:4:1:4:5 | ControlFlowNode for enter | -| has_defined_all_copy | exit | has_defined_all_copy.py:11:1:11:4 | ControlFlowNode for exit | -| has_defined_all_indirection | __file__ | has_defined_all_indirection.py:6:6:6:13 | ControlFlowNode for __file__ | -| has_defined_all_indirection | all_defined_foo_copy | has_defined_all_copy.py:6:1:6:20 | ControlFlowNode for all_defined_foo_copy | -| has_defined_all_indirection | enter | has_defined_all_indirection.py:2:1:2:5 | ControlFlowNode for enter | -| has_defined_all_indirection | exit | has_defined_all_indirection.py:6:1:6:4 | ControlFlowNode for exit | -| if_then_else | __file__ | if_then_else.py:16:6:16:13 | ControlFlowNode for __file__ | -| if_then_else | enter | if_then_else.py:2:1:2:5 | ControlFlowNode for enter | -| if_then_else | eval | if_then_else.py:11:8:11:11 | ControlFlowNode for eval | -| if_then_else | exit | if_then_else.py:16:1:16:4 | ControlFlowNode for exit | -| if_then_else | if_then_else_defined | if_then_else.py:7:5:7:24 | ControlFlowNode for if_then_else_defined | -| if_then_else | if_then_else_defined | if_then_else.py:12:9:12:28 | ControlFlowNode for if_then_else_defined | -| if_then_else | if_then_else_defined | if_then_else.py:14:9:14:28 | ControlFlowNode for if_then_else_defined | -| if_then_else_refined | SOURCE | if_then_else_refined.py:11:11:11:16 | ControlFlowNode for SOURCE | -| if_then_else_refined | SOURCE | if_then_else_refined.py:13:11:13:16 | ControlFlowNode for SOURCE | -| if_then_else_refined | __file__ | if_then_else_refined.py:19:6:19:13 | ControlFlowNode for __file__ | -| if_then_else_refined | check | if_then_else_refined.py:17:1:17:5 | ControlFlowNode for check | -| if_then_else_refined | enter | if_then_else_refined.py:4:1:4:5 | ControlFlowNode for enter | -| if_then_else_refined | eval | if_then_else_refined.py:10:4:10:7 | ControlFlowNode for eval | -| if_then_else_refined | exit | if_then_else_refined.py:19:1:19:4 | ControlFlowNode for exit | -| if_then_else_refined | globals | if_then_else_refined.py:17:24:17:30 | ControlFlowNode for globals | -| if_then_else_refined | src | if_then_else_refined.py:17:19:17:21 | ControlFlowNode for src | -| package.__init__ | __file__ | package/__init__.py:7:6:7:13 | ControlFlowNode for __file__ | -| package.__init__ | attr_used_in_subpackage | package/__init__.py:4:1:4:23 | ControlFlowNode for attr_used_in_subpackage | -| package.__init__ | enter | package/__init__.py:2:1:2:5 | ControlFlowNode for enter | -| package.__init__ | exit | package/__init__.py:7:1:7:4 | ControlFlowNode for exit | -| package.__init__ | package_attr | package/__init__.py:5:1:5:12 | ControlFlowNode for package_attr | -| package.subpackage2.__init__ | __file__ | package/subpackage2/__init__.py:6:6:6:13 | ControlFlowNode for __file__ | -| package.subpackage2.__init__ | enter | package/subpackage2/__init__.py:2:1:2:5 | ControlFlowNode for enter | -| package.subpackage2.__init__ | exit | package/subpackage2/__init__.py:6:1:6:4 | ControlFlowNode for exit | -| package.subpackage2.__init__ | subpackage2_attr | package/subpackage2/__init__.py:4:1:4:16 | ControlFlowNode for subpackage2_attr | -| package.subpackage.__init__ | __file__ | package/subpackage/__init__.py:14:6:14:13 | ControlFlowNode for __file__ | -| package.subpackage.__init__ | check | package/subpackage/__init__.py:12:1:12:5 | ControlFlowNode for check | -| package.subpackage.__init__ | enter | package/subpackage/__init__.py:2:1:2:5 | ControlFlowNode for enter | -| package.subpackage.__init__ | exit | package/subpackage/__init__.py:14:1:14:4 | ControlFlowNode for exit | -| package.subpackage.__init__ | globals | package/subpackage/__init__.py:12:79:12:85 | ControlFlowNode for globals | -| package.subpackage.__init__ | imported_attr | package/subpackage/__init__.py:7:16:7:55 | ControlFlowNode for ImportMember | -| package.subpackage.__init__ | imported_attr | package/subpackage/__init__.py:8:24:8:36 | ControlFlowNode for imported_attr | -| package.subpackage.__init__ | irrelevant_attr | package/subpackage/__init__.py:11:24:11:38 | ControlFlowNode for ImportMember | -| package.subpackage.__init__ | irrelevant_attr | package/subpackage/__init__.py:11:24:11:38 | ControlFlowNode for irrelevant_attr | -| package.subpackage.__init__ | submodule | package/subpackage/__init__.py:12:35:12:43 | ControlFlowNode for submodule | -| package.subpackage.__init__ | subpackage_attr | package/subpackage/__init__.py:4:1:4:15 | ControlFlowNode for subpackage_attr | -| package.subpackage.submodule | __file__ | package/subpackage/submodule.py:7:6:7:13 | ControlFlowNode for __file__ | -| package.subpackage.submodule | enter | package/subpackage/submodule.py:2:1:2:5 | ControlFlowNode for enter | -| package.subpackage.submodule | exit | package/subpackage/submodule.py:7:1:7:4 | ControlFlowNode for exit | -| package.subpackage.submodule | irrelevant_attr | package/subpackage/submodule.py:5:1:5:15 | ControlFlowNode for irrelevant_attr | -| package.subpackage.submodule | submodule_attr | package/subpackage/submodule.py:4:1:4:14 | ControlFlowNode for submodule_attr | -| refined | SOURCE | refined.py:12:25:12:30 | ControlFlowNode for SOURCE | -| refined | __file__ | refined.py:14:6:14:13 | ControlFlowNode for __file__ | -| refined | check | refined.py:12:1:12:5 | ControlFlowNode for check | -| refined | enter | refined.py:2:1:2:5 | ControlFlowNode for enter | -| refined | exit | refined.py:14:1:14:4 | ControlFlowNode for exit | -| refined | globals | refined.py:12:33:12:39 | ControlFlowNode for globals | -| refined | object | refined.py:4:14:4:19 | ControlFlowNode for object | -| simplistic_reexport | __file__ | simplistic_reexport.py:19:6:19:13 | ControlFlowNode for __file__ | -| simplistic_reexport | bar_attr | simplistic_reexport.py:6:17:6:24 | ControlFlowNode for ImportMember | -| simplistic_reexport | bar_attr | simplistic_reexport.py:10:19:10:26 | ControlFlowNode for bar_attr | -| simplistic_reexport | baz_attr | baz.py:4:1:4:8 | ControlFlowNode for baz_attr | -| simplistic_reexport | baz_attr | simplistic_reexport.py:17:19:17:26 | ControlFlowNode for baz_attr | -| simplistic_reexport | check | simplistic_reexport.py:17:1:17:5 | ControlFlowNode for check | -| simplistic_reexport | enter | baz.py:2:1:2:5 | ControlFlowNode for enter | -| simplistic_reexport | enter | simplistic_reexport.py:4:1:4:5 | ControlFlowNode for enter | -| simplistic_reexport | exit | baz.py:6:1:6:4 | ControlFlowNode for exit | -| simplistic_reexport | exit | simplistic_reexport.py:19:1:19:4 | ControlFlowNode for exit | -| simplistic_reexport | globals | simplistic_reexport.py:17:44:17:50 | ControlFlowNode for globals | +| attr_clash.__init__ | __file__ | attr_clash/__init__.py:6:6:6:13 | __file__ | +| attr_clash.__init__ | clashing_attr | attr_clash/__init__.py:4:1:4:13 | clashing_attr | +| attr_clash.__init__ | enter | attr_clash/__init__.py:2:1:2:5 | enter | +| attr_clash.__init__ | exit | attr_clash/__init__.py:6:1:6:4 | exit | +| attr_clash.clashing_attr | __file__ | attr_clash/clashing_attr.py:4:6:4:13 | __file__ | +| attr_clash.clashing_attr | enter | attr_clash/clashing_attr.py:2:1:2:5 | enter | +| attr_clash.clashing_attr | exit | attr_clash/clashing_attr.py:4:1:4:4 | exit | +| attr_clash.non_clashing_submodule | __file__ | attr_clash/non_clashing_submodule.py:4:6:4:13 | __file__ | +| attr_clash.non_clashing_submodule | enter | attr_clash/non_clashing_submodule.py:2:1:2:5 | enter | +| attr_clash.non_clashing_submodule | exit | attr_clash/non_clashing_submodule.py:4:1:4:4 | exit | +| bar | __file__ | bar.py:6:6:6:13 | __file__ | +| bar | bar_attr | bar.py:4:1:4:8 | bar_attr | +| bar | enter | bar.py:2:1:2:5 | enter | +| bar | exit | bar.py:6:1:6:4 | exit | +| baz | __file__ | baz.py:6:6:6:13 | __file__ | +| baz | baz_attr | baz.py:4:1:4:8 | baz_attr | +| baz | enter | baz.py:2:1:2:5 | enter | +| baz | exit | baz.py:6:1:6:4 | exit | +| block_flow_check | SOURCE | block_flow_check.py:12:25:12:30 | SOURCE | +| block_flow_check | __file__ | block_flow_check.py:14:6:14:13 | __file__ | +| block_flow_check | check | block_flow_check.py:12:1:12:5 | check | +| block_flow_check | enter | block_flow_check.py:2:1:2:5 | enter | +| block_flow_check | exit | block_flow_check.py:14:1:14:4 | exit | +| block_flow_check | globals | block_flow_check.py:12:33:12:39 | globals | +| block_flow_check | object | block_flow_check.py:4:14:4:19 | object | +| foo | __file__ | foo.py:14:6:14:13 | __file__ | +| foo | __private_foo_attr | foo.py:8:1:8:18 | __private_foo_attr | +| foo | bar_reexported | foo.py:11:8:11:10 | ImportExpr | +| foo | bar_reexported | foo.py:12:34:12:47 | bar_reexported | +| foo | check | foo.py:12:1:12:5 | check | +| foo | enter | foo.py:2:1:2:5 | enter | +| foo | exit | foo.py:14:1:14:4 | exit | +| foo | foo_attr | foo.py:5:1:5:8 | foo_attr | +| foo | globals | foo.py:12:71:12:77 | globals | +| generous_export | Exception | generous_export.py:16:11:16:19 | Exception | +| generous_export | SOURCE | generous_export.py:15:11:15:16 | SOURCE | +| generous_export | SOURCE | generous_export.py:20:25:20:30 | SOURCE | +| generous_export | __file__ | generous_export.py:22:6:22:13 | __file__ | +| generous_export | check | generous_export.py:20:1:20:5 | check | +| generous_export | enter | generous_export.py:2:1:2:5 | enter | +| generous_export | eval | generous_export.py:10:4:10:7 | eval | +| generous_export | exit | generous_export.py:22:1:22:4 | exit | +| generous_export | globals | generous_export.py:20:33:20:39 | globals | +| generous_export | object | generous_export.py:4:14:4:19 | object | +| generous_export | print | generous_export.py:15:5:15:9 | print | +| has_defined_all | __all__ | has_defined_all.py:7:1:7:7 | __all__ | +| has_defined_all | __file__ | has_defined_all.py:9:6:9:13 | __file__ | +| has_defined_all | all_defined_bar | has_defined_all.py:5:1:5:15 | all_defined_bar | +| has_defined_all | all_defined_foo | has_defined_all.py:4:1:4:15 | all_defined_foo | +| has_defined_all | enter | has_defined_all.py:2:1:2:5 | enter | +| has_defined_all | exit | has_defined_all.py:9:1:9:4 | exit | +| has_defined_all_copy | __all__ | has_defined_all_copy.py:9:1:9:7 | __all__ | +| has_defined_all_copy | __file__ | has_defined_all_copy.py:11:6:11:13 | __file__ | +| has_defined_all_copy | all_defined_bar_copy | has_defined_all_copy.py:7:1:7:20 | all_defined_bar_copy | +| has_defined_all_copy | all_defined_foo_copy | has_defined_all_copy.py:6:1:6:20 | all_defined_foo_copy | +| has_defined_all_copy | enter | has_defined_all_copy.py:4:1:4:5 | enter | +| has_defined_all_copy | exit | has_defined_all_copy.py:11:1:11:4 | exit | +| has_defined_all_indirection | __file__ | has_defined_all_indirection.py:6:6:6:13 | __file__ | +| has_defined_all_indirection | all_defined_foo_copy | has_defined_all_copy.py:6:1:6:20 | all_defined_foo_copy | +| has_defined_all_indirection | enter | has_defined_all_indirection.py:2:1:2:5 | enter | +| has_defined_all_indirection | exit | has_defined_all_indirection.py:6:1:6:4 | exit | +| if_then_else | __file__ | if_then_else.py:16:6:16:13 | __file__ | +| if_then_else | enter | if_then_else.py:2:1:2:5 | enter | +| if_then_else | eval | if_then_else.py:11:8:11:11 | eval | +| if_then_else | exit | if_then_else.py:16:1:16:4 | exit | +| if_then_else | if_then_else_defined | if_then_else.py:7:5:7:24 | if_then_else_defined | +| if_then_else | if_then_else_defined | if_then_else.py:12:9:12:28 | if_then_else_defined | +| if_then_else | if_then_else_defined | if_then_else.py:14:9:14:28 | if_then_else_defined | +| if_then_else_refined | SOURCE | if_then_else_refined.py:11:11:11:16 | SOURCE | +| if_then_else_refined | SOURCE | if_then_else_refined.py:13:11:13:16 | SOURCE | +| if_then_else_refined | __file__ | if_then_else_refined.py:19:6:19:13 | __file__ | +| if_then_else_refined | check | if_then_else_refined.py:17:1:17:5 | check | +| if_then_else_refined | enter | if_then_else_refined.py:4:1:4:5 | enter | +| if_then_else_refined | eval | if_then_else_refined.py:10:4:10:7 | eval | +| if_then_else_refined | exit | if_then_else_refined.py:19:1:19:4 | exit | +| if_then_else_refined | globals | if_then_else_refined.py:17:24:17:30 | globals | +| if_then_else_refined | src | if_then_else_refined.py:17:19:17:21 | src | +| package.__init__ | __file__ | package/__init__.py:7:6:7:13 | __file__ | +| package.__init__ | attr_used_in_subpackage | package/__init__.py:4:1:4:23 | attr_used_in_subpackage | +| package.__init__ | enter | package/__init__.py:2:1:2:5 | enter | +| package.__init__ | exit | package/__init__.py:7:1:7:4 | exit | +| package.__init__ | package_attr | package/__init__.py:5:1:5:12 | package_attr | +| package.subpackage2.__init__ | __file__ | package/subpackage2/__init__.py:6:6:6:13 | __file__ | +| package.subpackage2.__init__ | enter | package/subpackage2/__init__.py:2:1:2:5 | enter | +| package.subpackage2.__init__ | exit | package/subpackage2/__init__.py:6:1:6:4 | exit | +| package.subpackage2.__init__ | subpackage2_attr | package/subpackage2/__init__.py:4:1:4:16 | subpackage2_attr | +| package.subpackage.__init__ | __file__ | package/subpackage/__init__.py:14:6:14:13 | __file__ | +| package.subpackage.__init__ | check | package/subpackage/__init__.py:12:1:12:5 | check | +| package.subpackage.__init__ | enter | package/subpackage/__init__.py:2:1:2:5 | enter | +| package.subpackage.__init__ | exit | package/subpackage/__init__.py:14:1:14:4 | exit | +| package.subpackage.__init__ | globals | package/subpackage/__init__.py:12:79:12:85 | globals | +| package.subpackage.__init__ | imported_attr | package/subpackage/__init__.py:7:16:7:55 | After ImportMember | +| package.subpackage.__init__ | imported_attr | package/subpackage/__init__.py:8:24:8:36 | imported_attr | +| package.subpackage.__init__ | irrelevant_attr | package/subpackage/__init__.py:11:24:11:38 | After ImportMember | +| package.subpackage.__init__ | irrelevant_attr | package/subpackage/__init__.py:11:24:11:38 | irrelevant_attr | +| package.subpackage.__init__ | submodule | package/subpackage/__init__.py:12:35:12:43 | submodule | +| package.subpackage.__init__ | subpackage_attr | package/subpackage/__init__.py:4:1:4:15 | subpackage_attr | +| package.subpackage.submodule | __file__ | package/subpackage/submodule.py:7:6:7:13 | __file__ | +| package.subpackage.submodule | enter | package/subpackage/submodule.py:2:1:2:5 | enter | +| package.subpackage.submodule | exit | package/subpackage/submodule.py:7:1:7:4 | exit | +| package.subpackage.submodule | irrelevant_attr | package/subpackage/submodule.py:5:1:5:15 | irrelevant_attr | +| package.subpackage.submodule | submodule_attr | package/subpackage/submodule.py:4:1:4:14 | submodule_attr | +| refined | SOURCE | refined.py:12:25:12:30 | SOURCE | +| refined | __file__ | refined.py:14:6:14:13 | __file__ | +| refined | check | refined.py:12:1:12:5 | check | +| refined | enter | refined.py:2:1:2:5 | enter | +| refined | exit | refined.py:14:1:14:4 | exit | +| refined | globals | refined.py:12:33:12:39 | globals | +| refined | object | refined.py:4:14:4:19 | object | +| simplistic_reexport | __file__ | simplistic_reexport.py:19:6:19:13 | __file__ | +| simplistic_reexport | bar_attr | simplistic_reexport.py:6:17:6:24 | After ImportMember | +| simplistic_reexport | bar_attr | simplistic_reexport.py:10:19:10:26 | bar_attr | +| simplistic_reexport | baz_attr | baz.py:4:1:4:8 | baz_attr | +| simplistic_reexport | baz_attr | simplistic_reexport.py:17:19:17:26 | baz_attr | +| simplistic_reexport | check | simplistic_reexport.py:17:1:17:5 | check | +| simplistic_reexport | enter | baz.py:2:1:2:5 | enter | +| simplistic_reexport | enter | simplistic_reexport.py:4:1:4:5 | enter | +| simplistic_reexport | exit | baz.py:6:1:6:4 | exit | +| simplistic_reexport | exit | simplistic_reexport.py:19:1:19:4 | exit | +| simplistic_reexport | globals | simplistic_reexport.py:17:44:17:50 | globals | diff --git a/python/ql/test/experimental/import-resolution/importflow.ql b/python/ql/test/experimental/import-resolution/importflow.ql index a3e20123fc7..4fbc782abf5 100644 --- a/python/ql/test/experimental/import-resolution/importflow.ql +++ b/python/ql/test/experimental/import-resolution/importflow.ql @@ -3,6 +3,7 @@ import semmle.python.dataflow.new.DataFlow import semmle.python.ApiGraphs import utils.test.InlineExpectationsTest import semmle.python.dataflow.new.internal.ImportResolution +private import semmle.python.controlflow.internal.Cfg as Cfg /** A string that appears on the right hand side of an assignment. */ private class SourceString extends DataFlow::Node { @@ -45,13 +46,15 @@ private class VersionGuardedNode extends DataFlow::Node { VersionGuardedNode() { version in [2, 3] and - exists(If parent, CompareNode c | parent.getBody().contains(this.asExpr()) | + exists(If parent, Cfg::CompareNode c, Cfg::ControlFlowNode litCfg | + parent.getBody().contains(this.asExpr()) and + litCfg.getNode() = any(IntegerLiteral lit | lit.getValue() = version) + | c.operands(API::moduleImport("sys") .getMember("version_info") .getASubscript() .asSource() - .asCfgNode(), any(Eq eq), - any(IntegerLiteral lit | lit.getValue() = version).getAFlowNode()) + .asCfgNode(), any(Eq eq), litCfg) ) } diff --git a/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql b/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql index 8b52244478f..6173331a2dd 100644 --- a/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql +++ b/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql @@ -9,7 +9,7 @@ Expr assignedValue(Name n) { from Name def, DefinitionNode d where - d = def.getAFlowNode() and + d.getNode() = def and exists(assignedValue(def)) and not d.getValue().getNode() = assignedValue(def) select def.toString(), assignedValue(def) diff --git a/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql b/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql index c51707a65ff..e41f73f5b88 100644 --- a/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql +++ b/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql @@ -8,4 +8,4 @@ where not a instanceof ExprStmt and a.getScope() = s and s instanceof Function -select a.getLocation().getStartLine(), s.getName(), a, count(a.getAFlowNode()) +select a.getLocation().getStartLine(), s.getName(), a, count(ControlFlowNode n | n.getNode() = a) diff --git a/python/ql/test/library-tests/dataflow/tainttracking/TestTaintLib.qll b/python/ql/test/library-tests/dataflow/tainttracking/TestTaintLib.qll index f46f08aa509..cb014631208 100644 --- a/python/ql/test/library-tests/dataflow/tainttracking/TestTaintLib.qll +++ b/python/ql/test/library-tests/dataflow/tainttracking/TestTaintLib.qll @@ -44,7 +44,7 @@ query predicate test_taint(string arg_location, string test_res, string scope_na // TODO: Replace with `hasFlowToExpr` once that is working if TestTaintTrackingFlow::flowTo(any(DataFlow::Node n | - n.(DataFlow::CfgNode).getNode() = arg.getAFlowNode() + n.(DataFlow::CfgNode).getNode().getNode() = arg )) then has_taint = true else has_taint = false