Skip to content
Draft
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
Expand Up @@ -564,8 +564,10 @@ class EssaVariable extends Ssa::SsaDefinition {
* library. Provides the same interface as legacy
* `semmle.python.essa.SsaCompute::AdjacentUses`.
*/
cached
module AdjacentUses {
/** Holds if `nodeFrom` and `nodeTo` are adjacent uses of the same SSA variable. */
cached
predicate adjacentUseUse(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo) {
exists(CfgImpl::BasicBlock bb1, int i1, CfgImpl::BasicBlock bb2, int i2 |
Impl::adjacentUseUse(bb1, i1, bb2, i2, _, _) and
Expand All @@ -575,6 +577,7 @@ module AdjacentUses {
}

/** Holds if `use` is a first use of definition `def`. */
cached
predicate firstUse(Ssa::SsaDefinition def, Cfg::NameNode use) {
exists(CfgImpl::BasicBlock bb, int i |
Impl::firstUse(def, bb, i, _) and
Expand All @@ -586,6 +589,7 @@ module AdjacentUses {
* Holds if `use` is any reachable use of definition `def`. Combines
* `firstUse` with transitive use-use adjacency.
*/
cached
predicate useOfDef(Ssa::SsaDefinition def, Cfg::NameNode use) {
firstUse(def, use)
or
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
exposed_first_use_count
| 9 |
exposed_adjacent_use_count
| 1 |
exposed_use_of_def_count
| 10 |
first_use_projection_mismatch_count
| 0 |
adjacent_use_projection_mismatch_count
| 0 |
use_of_def_expansion_mismatch_count
| 0 |
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import python
private import semmle.python.controlflow.internal.AstNodeImpl as CfgImpl
private import semmle.python.controlflow.internal.Cfg as Cfg
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl

private predicate projectedFirstUse(SsaImpl::Definition def, Cfg::NameNode use) {
exists(CfgImpl::BasicBlock bb, int i |
SsaImpl::Impl::firstUse(def, bb, i, _) and
use = bb.getNode(i)
)
}

private predicate projectedAdjacentUse(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo) {
exists(CfgImpl::BasicBlock bb1, int i1, CfgImpl::BasicBlock bb2, int i2 |
SsaImpl::Impl::adjacentUseUse(bb1, i1, bb2, i2, _, _) and
nodeFrom = bb1.getNode(i1) and
nodeTo = bb2.getNode(i2)
)
}

private predicate expandedUseOfDef(SsaImpl::Definition def, Cfg::NameNode use) {
exists(Cfg::NameNode first |
SsaImpl::AdjacentUses::firstUse(def, first) and
SsaImpl::AdjacentUses::adjacentUseUse*(first, use)
)
}

query int exposed_first_use_count() {
result =
count(SsaImpl::Definition def, Cfg::NameNode use | SsaImpl::AdjacentUses::firstUse(def, use))
}

query int exposed_adjacent_use_count() {
result =
count(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo |
SsaImpl::AdjacentUses::adjacentUseUse(nodeFrom, nodeTo)
)
}

query int exposed_use_of_def_count() {
result =
count(SsaImpl::Definition def, Cfg::NameNode use | SsaImpl::AdjacentUses::useOfDef(def, use))
}

query int first_use_projection_mismatch_count() {
result =
count(SsaImpl::Definition def, Cfg::NameNode use |
SsaImpl::AdjacentUses::firstUse(def, use) and not projectedFirstUse(def, use)
or
projectedFirstUse(def, use) and not SsaImpl::AdjacentUses::firstUse(def, use)
)
}

query int adjacent_use_projection_mismatch_count() {
result =
count(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo |
SsaImpl::AdjacentUses::adjacentUseUse(nodeFrom, nodeTo) and
not projectedAdjacentUse(nodeFrom, nodeTo)
or
projectedAdjacentUse(nodeFrom, nodeTo) and
not SsaImpl::AdjacentUses::adjacentUseUse(nodeFrom, nodeTo)
)
}

query int use_of_def_expansion_mismatch_count() {
result =
count(SsaImpl::Definition def, Cfg::NameNode use |
SsaImpl::AdjacentUses::useOfDef(def, use) and not expandedUseOfDef(def, use)
or
expandedUseOfDef(def, use) and not SsaImpl::AdjacentUses::useOfDef(def, use)
)
}
5 changes: 5 additions & 0 deletions python/ql/test/library-tests/dataflow-new-ssa/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ def basic_assign(): # $ def=basic_assign
return y # $ use=y


def repeated_use(x): # $ def=repeated_use def=x
first = x # $ def=first use=x
return x + first # $ use=x use=first


def reassignment(): # $ def=reassignment
x = 1
x = 2 # $ def=x
Expand Down