From f138fc0d2d949b3c0d76d4a068e9e738054badf6 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 21 Nov 2023 13:54:02 +0100 Subject: [PATCH 1/2] Python: Test demonstrating need for phi-read-nodes Or for a data flow node filling that role, at least. --- .../dataflow/use-use-flow/read_explosion.py | 36 ++++++++++++++++++ .../use-use-flow/use-use-counts.expected | 24 ++++++++++++ .../dataflow/use-use-flow/use-use-counts.ql | 37 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/use-use-flow/read_explosion.py create mode 100644 python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.expected create mode 100644 python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.ql diff --git a/python/ql/test/experimental/dataflow/use-use-flow/read_explosion.py b/python/ql/test/experimental/dataflow/use-use-flow/read_explosion.py new file mode 100644 index 000000000000..ff08f91619dd --- /dev/null +++ b/python/ql/test/experimental/dataflow/use-use-flow/read_explosion.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: + 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 \ No newline at end of file diff --git a/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.expected b/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.expected new file mode 100644 index 000000000000..5d1b42e1f311 --- /dev/null +++ b/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.expected @@ -0,0 +1,24 @@ +implicit_use_count +| 0 | +implicit_use +source_use_count +| 6 | +source_use +| read_explosion.py:13:15:13:15 | ControlFlowNode for x | +| read_explosion.py:15:13:15:13 | ControlFlowNode for x | +| read_explosion.py:17:11:17:11 | ControlFlowNode for x | +| read_explosion.py:24:15:24:15 | ControlFlowNode for x | +| read_explosion.py:26:13:26:13 | ControlFlowNode for x | +| read_explosion.py:28:11:28:11 | ControlFlowNode for x | +use_use_edge_count +| 9 | +use_use_edge +| read_explosion.py:13:15:13:15 | ControlFlowNode for x | read_explosion.py:24:15:24:15 | ControlFlowNode for x | +| read_explosion.py:13:15:13:15 | ControlFlowNode for x | read_explosion.py:26:13:26:13 | ControlFlowNode for x | +| read_explosion.py:13:15:13:15 | ControlFlowNode for x | read_explosion.py:28:11:28:11 | ControlFlowNode for x | +| read_explosion.py:15:13:15:13 | ControlFlowNode for x | read_explosion.py:24:15:24:15 | ControlFlowNode for x | +| read_explosion.py:15:13:15:13 | ControlFlowNode for x | read_explosion.py:26:13:26:13 | ControlFlowNode for x | +| read_explosion.py:15:13:15:13 | ControlFlowNode for x | read_explosion.py:28:11:28:11 | ControlFlowNode for x | +| read_explosion.py:17:11:17:11 | ControlFlowNode for x | read_explosion.py:24:15:24:15 | ControlFlowNode for x | +| read_explosion.py:17:11:17:11 | ControlFlowNode for x | read_explosion.py:26:13:26:13 | ControlFlowNode for x | +| read_explosion.py:17:11:17:11 | ControlFlowNode for x | read_explosion.py:28:11:28:11 | ControlFlowNode for x | diff --git a/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.ql b/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.ql new file mode 100644 index 000000000000..ff18cc66f68b --- /dev/null +++ b/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.ql @@ -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) + ) +} From 077e51c6c6b7d759d00b521bc0d25f90557d9f32 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 21 Nov 2023 15:47:18 +0100 Subject: [PATCH 2/2] Python: fix test output --- .../use-use-flow/use-use-counts.expected | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.expected b/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.expected index 5d1b42e1f311..92f5114fb8f4 100644 --- a/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.expected +++ b/python/ql/test/experimental/dataflow/use-use-flow/use-use-counts.expected @@ -4,21 +4,21 @@ implicit_use source_use_count | 6 | source_use -| read_explosion.py:13:15:13:15 | ControlFlowNode for x | -| read_explosion.py:15:13:15:13 | ControlFlowNode for x | -| read_explosion.py:17:11:17:11 | ControlFlowNode for x | -| read_explosion.py:24:15:24:15 | ControlFlowNode for x | -| read_explosion.py:26:13:26:13 | ControlFlowNode for x | -| read_explosion.py:28:11:28:11 | ControlFlowNode for x | +| 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:13:15:13:15 | ControlFlowNode for x | read_explosion.py:24:15:24:15 | ControlFlowNode for x | -| read_explosion.py:13:15:13:15 | ControlFlowNode for x | read_explosion.py:26:13:26:13 | ControlFlowNode for x | -| read_explosion.py:13:15:13:15 | ControlFlowNode for x | read_explosion.py:28:11:28:11 | ControlFlowNode for x | -| read_explosion.py:15:13:15:13 | ControlFlowNode for x | read_explosion.py:24:15:24:15 | ControlFlowNode for x | -| read_explosion.py:15:13:15:13 | ControlFlowNode for x | read_explosion.py:26:13:26:13 | ControlFlowNode for x | -| read_explosion.py:15:13:15:13 | ControlFlowNode for x | read_explosion.py:28:11:28:11 | ControlFlowNode for x | -| read_explosion.py:17:11:17:11 | ControlFlowNode for x | read_explosion.py:24:15:24:15 | ControlFlowNode for x | -| read_explosion.py:17:11:17:11 | ControlFlowNode for x | read_explosion.py:26:13:26:13 | ControlFlowNode for x | -| read_explosion.py:17:11:17:11 | ControlFlowNode for x | read_explosion.py:28:11:28:11 | ControlFlowNode for x | +| 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 |