Python: migrate remaining tests off getAFlowNode() and fix star-import SSA step

Sweep the last few uses of legacy AstNode.getAFlowNode() in tests over to
explicit ControlFlowNode joins after the shared-CFG migration. importflow.ql
needs the new Cfg::ControlFlowNode/CompareNode types because DataFlow::Node.
asCfgNode() now returns the shared-CFG node.

Also extend ImportResolution::allowedEssaImportStep to walk back through
uncertain-write SSA inputs, so that a later 'from X import *' does not hide
the preceding explicit (re)assignment from module-export resolution. Without
this, a reassigned name that survives a wildcard import was no longer
recognised as the module export. Rebless ModuleExport.expected to drop the
legacy 'ControlFlowNode for' toString prefix and pick up the two correct rows
exposed by the fix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
yoff
2026-05-28 13:13:11 +00:00
parent 04b130f57f
commit de7744950f
7 changed files with 139 additions and 128 deletions

View File

@@ -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.
}
/**

View File

@@ -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)
)

View File

@@ -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 |

View File

@@ -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)
)
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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