Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python: Use more general definitions #15080

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

yoff
Copy link
Contributor

@yoff yoff commented Dec 12, 2023

We now formulate local flow steps based on
DefinitionNodes, instead of just
AssignmentDefinitions.

This collects all logic around definitions into
DefinitionNode and avoids extra cases in the
flow relations.

It also allows a few more definitions needed for variable
capture. These are currently excluded from AssignmentDefinition
because they are not TEssaNodeDefinitions because
they are not considered live.
(SsaComputeImpl::variableDefine holds, but
Liveness::liveAtExit does not).

DefinitionNode includes parameter definitions
from default values, which should be jump steps.
So we split the definitions into local and jumps
by looking at the enclosing callables.

DefinitionNode did not include with-definitions,
so that has been added. Like parameter definitions,
this case of DefinitionNode must be excluded from
assignment_definition.

Finally, we incur a dataflow inconsistency for a
non-sensical assignment in test code. This we simply accept.

The code reads

len(unknown()) = "foo"

which makes the target of the flow edge a post-update node.

We now formulate local flow steps based on
`DefinitionNode`s, instead of just
`AssignmentDefinition`s.

This collects all logic around definitions into
`DefinitionNode` and avoids extra cases in the
flow relations.

It also allows a few more definitions needed for variable
capture. These are currently excluded from `AssignmentDefinition`
because they are not `TEssaNodeDefinition`s because
they are not considered live.
(`SsaComputeImpl::variableDefine` holds, but
`Liveness::liveAtExit` does not).

`DefinitionNode` includes parameter definitions
from default values, which should be jump steps.
So we split the definitions into local and jumps
by looking at the enclosing callables.

`DefinitionNode` did not include `with`-definitions,
so that has been added. Like parameter definitions,
this case of `DefinitionNode` must be excluded from
`assignment_definition`.

Finally, we incur a dataflow inconsistency for a
non-sensical assignment in test code. This we simply accept.

The code reads

```python
len(unknown()) = "foo"
```

which makes the target of the flow edge a post-update node.
@yoff yoff force-pushed the python/local-flow-general-definitions branch from b0d5366 to 515e8fd Compare December 13, 2023 13:38
@yoff yoff marked this pull request as ready for review December 13, 2023 14:02
@yoff yoff requested a review from a team as a code owner December 13, 2023 14:02
@yoff yoff added Awaiting evaluation Do not merge yet, this PR is waiting for an evaluation to finish no-change-note-required This PR does not need a change note labels Dec 13, 2023
@yoff
Copy link
Contributor Author

yoff commented Dec 13, 2023

Performance looks fine (unchanged), but there is a small number of alert differences.

Edit: Sorry, I looked at the earlier experiment. The new one has some failures related to the internet that I have asked it to retry. Apart from that, performance is unchanged, alerts are unchanged, and the meta alerts show that we have a richer flow relation.

Copy link
Member

@RasmusWL RasmusWL left a comment

Choose a reason for hiding this comment

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

Apart from the two comment NITS, overall LGTM 👍

I think there's something slightly strange about DefinitionNode containing with, since when you look into the semantics it's not just a straight assignment (but rather, the value of __enter__()/await __aenter__()). However, since DefinitionNode includes for at the moment, I think it's fair game to also include with 🤷‍♂️


It also allows a few more definitions needed for variable
capture. These are currently excluded from AssignmentDefinition
because they are not TEssaNodeDefinitions because
they are not considered live.
(SsaComputeImpl::variableDefine holds, but
Liveness::liveAtExit does not).

This seems to be your intuition for the additional flow we achieve with this change. I was hoping to see this reflected in some of our tests. Can you add a test that illustrates this, that isn't about variable capture?

python/ql/lib/semmle/python/Flow.qll Outdated Show resolved Hide resolved
python/ql/lib/semmle/python/Flow.qll Outdated Show resolved Hide resolved
@RasmusWL
Copy link
Member

I'm a little undecided around whether a change-note is required... I guess it's fine without one

Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
@yoff yoff marked this pull request as draft December 15, 2023 07:25
@yoff
Copy link
Contributor Author

yoff commented Dec 15, 2023

Converting to draft until we know more accurately what is added here.

@RasmusWL
Copy link
Member

We agreed offline to take a closer look at the new edges being added from this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting evaluation Do not merge yet, this PR is waiting for an evaluation to finish 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