diff --git a/python/ql/test/experimental/dataflow/def-use-flow/def_use_counts.expected b/python/ql/test/experimental/dataflow/def-use-flow/def_use_counts.expected new file mode 100644 index 000000000000..1fe1d1d105a5 --- /dev/null +++ b/python/ql/test/experimental/dataflow/def-use-flow/def_use_counts.expected @@ -0,0 +1,31 @@ +def_count +| 4 | +def +| def_use_flow.py:10:5:10:5 | Essa node definition | +| def_use_flow.py:17:11:17:11 | Essa node definition | +| def_use_flow.py:19:9:19:9 | Essa node definition | +| def_use_flow.py:21:7:21:7 | Essa node definition | +implicit_use_count +| 0 | +implicit_use +source_use_count +| 3 | +source_use +| def_use_flow.py:28:15:28:15 | ControlFlowNode for x | +| def_use_flow.py:30:13:30:13 | ControlFlowNode for x | +| def_use_flow.py:32:11:32:11 | ControlFlowNode for x | +def_use_edge_count +| 12 | +def_use_edge +| def_use_flow.py:10:5:10:5 | SSA variable x | def_use_flow.py:28:15:28:15 | ControlFlowNode for x | +| def_use_flow.py:10:5:10:5 | SSA variable x | def_use_flow.py:30:13:30:13 | ControlFlowNode for x | +| def_use_flow.py:10:5:10:5 | SSA variable x | def_use_flow.py:32:11:32:11 | ControlFlowNode for x | +| def_use_flow.py:17:11:17:11 | SSA variable x | def_use_flow.py:28:15:28:15 | ControlFlowNode for x | +| def_use_flow.py:17:11:17:11 | SSA variable x | def_use_flow.py:30:13:30:13 | ControlFlowNode for x | +| def_use_flow.py:17:11:17:11 | SSA variable x | def_use_flow.py:32:11:32:11 | ControlFlowNode for x | +| def_use_flow.py:19:9:19:9 | SSA variable x | def_use_flow.py:28:15:28:15 | ControlFlowNode for x | +| def_use_flow.py:19:9:19:9 | SSA variable x | def_use_flow.py:30:13:30:13 | ControlFlowNode for x | +| def_use_flow.py:19:9:19:9 | SSA variable x | def_use_flow.py:32:11:32:11 | ControlFlowNode for x | +| def_use_flow.py:21:7:21:7 | SSA variable x | def_use_flow.py:28:15:28:15 | ControlFlowNode for x | +| def_use_flow.py:21:7:21:7 | SSA variable x | def_use_flow.py:30:13:30:13 | ControlFlowNode for x | +| def_use_flow.py:21:7:21:7 | SSA variable x | def_use_flow.py:32:11:32:11 | ControlFlowNode for x | diff --git a/python/ql/test/experimental/dataflow/def-use-flow/def_use_counts.ql b/python/ql/test/experimental/dataflow/def-use-flow/def_use_counts.ql new file mode 100644 index 000000000000..0f0d5953a367 --- /dev/null +++ b/python/ql/test/experimental/dataflow/def-use-flow/def_use_counts.ql @@ -0,0 +1,47 @@ +import python +private import semmle.python.dataflow.new.internal.DataFlowPrivate + +query int def_count() { + exists(SsaSourceVariable x | x.getName() = "x" | + result = count(EssaNodeDefinition def | def.getSourceVariable() = x) + ) +} + +query EssaNodeDefinition def() { + exists(SsaSourceVariable x | x.getName() = "x" | result.getSourceVariable() = x) +} + +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 def_use_edge_count() { + exists(SsaSourceVariable x | x.getName() = "x" | + result = + count(EssaVariable v, NameNode use | + v.getSourceVariable() = x and + use = x.getAUse() and + LocalFlow::defToFirstUse(v, use) + ) + ) +} + +query predicate def_use_edge(EssaVariable v, NameNode use) { + exists(SsaSourceVariable x | x.getName() = "x" | + v.getSourceVariable() = x and + use = x.getAUse() and + LocalFlow::defToFirstUse(v, use) + ) +} diff --git a/python/ql/test/experimental/dataflow/def-use-flow/def_use_flow.py b/python/ql/test/experimental/dataflow/def-use-flow/def_use_flow.py new file mode 100644 index 000000000000..01ec517e3f67 --- /dev/null +++ b/python/ql/test/experimental/dataflow/def-use-flow/def_use_flow.py @@ -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): + 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) + + def use(v): + # this could just be `pass` but we do not want it optimized away. + y = v+2 \ No newline at end of file