Sitelet https://web.archive.org/web/20260404113137/https://github.com/github/codeql/pull/6650
Skip to content

Python: Import time dataflow#6650

Merged
tausbn merged 13 commits intogithub:mainfrom
yoff:python-dataflow/init-time
Oct 12, 2021
Merged

Python: Import time dataflow#6650
tausbn merged 13 commits intogithub:mainfrom
yoff:python-dataflow/init-time

Conversation

@yoff
Copy link
Copy Markdown
Contributor

@yoff yoff commented Sep 9, 2021

This PR addresses https://github.com/github/codeql-python-team/issues/417. The discussion in that issue outlines the strategy.

Basically, data flow occurs at two different times, import time and runtime, and there is therefor really two dataflow graphs. We create a single local flow relation by partitioning code into import time code and runtime code based on whether code occurs at the top level in the program text. This is mostly correct, except functions (or classes, methods, etc..) called from the top-level should also contribute to import time flow. This oversight means that we may get some incorrect ultimate definitions (those succeeded by function calls), leading to some extra flow.

@yoff yoff requested a review from a team as a code owner September 9, 2021 13:58
@github-actions github-actions bot added the Python label Sep 9, 2021
@yoff yoff added no-change-note-required This PR does not need a change note and removed Python labels Sep 9, 2021
Copy link
Copy Markdown
Contributor

@tausbn tausbn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments and suggestions, otherwise I think this looks good! 👍
I found the tests quite difficult to read because of the verbosity, though, so i'm not 100% sure that I would have spotted any mistakes.

| examples.py:0:0:0:0 | GSSA Variable SOURCE | examples.py:27:15:27:20 | ControlFlowNode for SOURCE |
| examples.py:0:0:0:0 | GSSA Variable object | examples.py:6:13:6:18 | ControlFlowNode for object |
| examples.py:6:1:6:20 | ControlFlowNode for ClassExpr | examples.py:6:7:6:11 | GSSA Variable MyObj |
| examples.py:6:7:6:11 | ControlFlowNode for MyObj | examples.py:0:0:0:0 | ModuleVariableNode for Global Variable MyObj in Module examples |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, these ModuleVariableNode toStrings are really wordy. I wonder if we should just change the implementation to, say,

  override string toString() {
    result = "ModuleVariableNode for " + mod.getName() + "." + var.getId()
  }

to save a bit of space.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be nicer, is it OK to do it in this PR?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine by me. I expect a lot of test output will change, but most of the changes will be somewhat trivial to inspect.

Comment on lines +262 to +266
exists(SsaVariable def |
def = any(SsaVariable var).getAnUltimateDefinition() and
def.getDefinition() = nodeFrom.asCfgNode() and
def.getVariable() = nodeTo.(ModuleVariableNode).getVariable()
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I guess it's somewhat debatable whether this is flow that happens at import time or at runtime. Ultimately I guess it doesn't matter, since there's no runtime reading of ModuleVariableNodes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, this is at the interface. I take it you mean no import time reading of ModuleVariableNodes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're quite right. I meant import time.

I think part of what bothers me is that this predicate claims to talk about local flow, but I would not classify the writing of a value to a module variable node as "local". Everywhere else, we would treat this as a jump step.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is because "everywhere else" has been runtime flow so far. Seeing as it is on the interface, though, I am not really against moving it. That would put the line between the ultimate definition of an SSA variable and the corresponding module variable node. Let us try and see how that looks :-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The immediate effect is that we do not see this flow in the tests, because of how they are written, but that could be fixed..

Co-authored-by: Taus <tausbn@github.com>
@github-actions github-actions bot added the Python label Oct 7, 2021
@yoff yoff requested a review from tausbn October 8, 2021 14:58

def set_foo():
global foo
foo = SOURCE #$ runtimeFlow="ModuleVariableNode for multiphase.SOURCE, l:-31 -> SOURCE" MISSING:importTimeFlow="ModuleVariableNode for multiphase.foo"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from this mention of importTimeFlow, I see no other references. That seems... Odd. Perhaps we need to extend the tests?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, ImportTimeLocalFlowTest currently only considers flow to ModuleVariableNodes, but such flow no longer exists at import time.

Copy link
Copy Markdown
Contributor

@tausbn tausbn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made a few suggestions, but apart from that I think this looks good. 👍

yoff and others added 2 commits October 11, 2021 13:00
@yoff yoff requested a review from tausbn October 11, 2021 12:29
Copy link
Copy Markdown
Contributor

@tausbn tausbn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Splendid! In it goes. 🚀

@tausbn tausbn merged commit 75c4d6a into github:main Oct 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-change-note-required This PR does not need a change note Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants