Skip to content

Python: Test demonstrating the need for phi-read-nodes #14858

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

Merged
merged 2 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# This test file is inspired by
# `csharp/ql/test/library-tests/dataflow/local/UseUseExplosion.cs`
# but with `n=3` kept small, since we do have the explosion.

cond = ...

# global variables are slightly special,
# so we go into a function scope
def scope():
x = 0

if(cond > 3):
Copy link
Contributor

Choose a reason for hiding this comment

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

You could also add a test for normal phi nodes, i.e. something like

    if(cond > 3):
      if(cond > 2):
        if(cond > 1):
           pass
        else:
          x = 1
      else:
        x = 2
    else:
      x = 3

    if(cond > 3):
      if(cond > 2):
        if(cond > 1):
           pass
        else:
          use(x)
      else:
        use(x)
    else:
      use(x)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I put that in #14861. (Looks like I came to the exact same example :-))

if(cond > 2):
if(cond > 1):
pass
else:
use(x)
else:
use(x)
else:
use(x)

if(cond > 3):
if(cond > 2):
if(cond > 1):
pass
else:
use(x)
else:
use(x)
else:
use(x)

def use(v):
# this could just be `pass` but we do not want it optimized away.
y = v+2
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
implicit_use_count
| 0 |
implicit_use
source_use_count
| 6 |
source_use
| read_explosion.py:17:15:17:15 | ControlFlowNode for x |
| read_explosion.py:19:13:19:13 | ControlFlowNode for x |
| read_explosion.py:21:11:21:11 | ControlFlowNode for x |
| read_explosion.py:28:15:28:15 | ControlFlowNode for x |
| read_explosion.py:30:13:30:13 | ControlFlowNode for x |
| read_explosion.py:32:11:32:11 | ControlFlowNode for x |
use_use_edge_count
| 9 |
use_use_edge
| read_explosion.py:17:15:17:15 | ControlFlowNode for x | read_explosion.py:28:15:28:15 | ControlFlowNode for x |
| read_explosion.py:17:15:17:15 | ControlFlowNode for x | read_explosion.py:30:13:30:13 | ControlFlowNode for x |
| read_explosion.py:17:15:17:15 | ControlFlowNode for x | read_explosion.py:32:11:32:11 | ControlFlowNode for x |
| read_explosion.py:19:13:19:13 | ControlFlowNode for x | read_explosion.py:28:15:28:15 | ControlFlowNode for x |
| read_explosion.py:19:13:19:13 | ControlFlowNode for x | read_explosion.py:30:13:30:13 | ControlFlowNode for x |
| read_explosion.py:19:13:19:13 | ControlFlowNode for x | read_explosion.py:32:11:32:11 | ControlFlowNode for x |
| read_explosion.py:21:11:21:11 | ControlFlowNode for x | read_explosion.py:28:15:28:15 | ControlFlowNode for x |
| read_explosion.py:21:11:21:11 | ControlFlowNode for x | read_explosion.py:30:13:30:13 | ControlFlowNode for x |
| read_explosion.py:21:11:21:11 | ControlFlowNode for x | read_explosion.py:32:11:32:11 | ControlFlowNode for x |
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import python
private import semmle.python.dataflow.new.internal.DataFlowPrivate

query int implicit_use_count() {
exists(SsaSourceVariable x | x.getName() = "x" | result = count(x.getAnImplicitUse()))
}

query ControlFlowNode implicit_use() {
exists(SsaSourceVariable x | x.getName() = "x" | result = x.getAnImplicitUse())
}

query int source_use_count() {
exists(SsaSourceVariable x | x.getName() = "x" | result = count(x.getASourceUse()))
}

query ControlFlowNode source_use() {
exists(SsaSourceVariable x | x.getName() = "x" | result = x.getASourceUse())
}

query int use_use_edge_count() {
exists(SsaSourceVariable x | x.getName() = "x" |
result =
count(NameNode use1, NameNode use2 |
use1 = x.getAUse() and
use2 = x.getAUse() and
LocalFlow::useToNextUse(use1, use2)
)
)
}

query predicate use_use_edge(NameNode use1, NameNode use2) {
exists(SsaSourceVariable x | x.getName() = "x" |
use1 = x.getAUse() and
use2 = x.getAUse() and
LocalFlow::useToNextUse(use1, use2)
)
}