From 054af504299c706b140e1fcea3324ecf31f4e47c Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 20 Aug 2026 13:14:50 +0200 Subject: [PATCH] Ruby: Document missing BeginExpr flow. --- .../dataflow/local/DataflowStep.expected | 45 ++++++++++++++++-- .../dataflow/local/Nodes.expected | 34 ++++++++++++++ .../dataflow/local/TaintStep.expected | 46 +++++++++++++++++-- .../dataflow/local/local_dataflow.rb | 26 ++++++++++- 4 files changed, 144 insertions(+), 7 deletions(-) diff --git a/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected b/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected index 7122b4c0ae2f..f9b7cad4c35f 100644 --- a/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected +++ b/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected @@ -2504,9 +2504,9 @@ | UseUseExplosion.rb:24:5:25:7 | use | UseUseExplosion.rb:1:1:26:3 | C | | local_dataflow.rb:1:1:7:3 | self (foo) | local_dataflow.rb:3:8:3:10 | self | | local_dataflow.rb:1:1:7:3 | self in foo | local_dataflow.rb:1:1:7:3 | self (foo) | -| local_dataflow.rb:1:1:150:3 | x | local_dataflow.rb:10:9:10:9 | x | -| local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self | -| local_dataflow.rb:1:1:150:3 | self in local_dataflow.rb | local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | +| local_dataflow.rb:1:1:174:4 | x | local_dataflow.rb:10:9:10:9 | x | +| local_dataflow.rb:1:1:174:4 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self | +| local_dataflow.rb:1:1:174:4 | self in local_dataflow.rb | local_dataflow.rb:1:1:174:4 | self (local_dataflow.rb) | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:1:9:1:9 | a | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:2:7:2:7 | a | | local_dataflow.rb:2:3:2:3 | b | local_dataflow.rb:3:13:3:13 | b | @@ -2979,3 +2979,42 @@ | local_dataflow.rb:147:9:147:9 | [post] x | local_dataflow.rb:148:9:148:9 | x | | local_dataflow.rb:147:9:147:9 | x | local_dataflow.rb:148:9:148:9 | x | | local_dataflow.rb:148:5:148:10 | call to use | local_dataflow.rb:132:12:148:10 | then ... | +| local_dataflow.rb:152:1:174:3 | self (begin_expr) | local_dataflow.rb:154:9:154:21 | self | +| local_dataflow.rb:152:1:174:3 | self (begin_expr) | local_dataflow.rb:155:9:155:17 | self | +| local_dataflow.rb:152:1:174:3 | self in begin_expr | local_dataflow.rb:152:1:174:3 | self (begin_expr) | +| local_dataflow.rb:152:16:152:16 | r | local_dataflow.rb:152:16:152:16 | r | +| local_dataflow.rb:152:16:152:16 | r | local_dataflow.rb:154:26:154:26 | r | +| local_dataflow.rb:153:3:153:3 | x | local_dataflow.rb:161:8:161:8 | x | +| local_dataflow.rb:154:9:154:21 | [post] self | local_dataflow.rb:157:9:157:17 | self | +| local_dataflow.rb:154:9:154:21 | self | local_dataflow.rb:157:9:157:17 | self | +| local_dataflow.rb:154:26:154:26 | r | local_dataflow.rb:164:26:164:26 | r | +| local_dataflow.rb:155:9:155:17 | [post] self | local_dataflow.rb:157:9:157:17 | self | +| local_dataflow.rb:155:9:155:17 | [post] self | local_dataflow.rb:159:9:159:17 | self | +| local_dataflow.rb:155:9:155:17 | self | local_dataflow.rb:157:9:157:17 | self | +| local_dataflow.rb:155:9:155:17 | self | local_dataflow.rb:159:9:159:17 | self | +| local_dataflow.rb:157:9:157:17 | [post] self | local_dataflow.rb:159:9:159:17 | self | +| local_dataflow.rb:157:9:157:17 | call to source | local_dataflow.rb:156:13:157:17 | then ... | +| local_dataflow.rb:157:9:157:17 | self | local_dataflow.rb:159:9:159:17 | self | +| local_dataflow.rb:159:9:159:17 | [post] self | local_dataflow.rb:161:3:161:9 | self | +| local_dataflow.rb:159:9:159:17 | call to source | local_dataflow.rb:158:7:159:17 | ensure ... | +| local_dataflow.rb:159:9:159:17 | self | local_dataflow.rb:161:3:161:9 | self | +| local_dataflow.rb:161:3:161:9 | [post] self | local_dataflow.rb:164:9:164:21 | self | +| local_dataflow.rb:161:3:161:9 | [post] self | local_dataflow.rb:165:9:165:17 | self | +| local_dataflow.rb:161:3:161:9 | self | local_dataflow.rb:164:9:164:21 | self | +| local_dataflow.rb:161:3:161:9 | self | local_dataflow.rb:165:9:165:17 | self | +| local_dataflow.rb:163:3:163:3 | y | local_dataflow.rb:173:8:173:8 | y | +| local_dataflow.rb:164:9:164:21 | [post] self | local_dataflow.rb:167:9:167:17 | self | +| local_dataflow.rb:164:9:164:21 | self | local_dataflow.rb:167:9:167:17 | self | +| local_dataflow.rb:165:9:165:17 | [post] self | local_dataflow.rb:167:9:167:17 | self | +| local_dataflow.rb:165:9:165:17 | [post] self | local_dataflow.rb:169:9:169:17 | self | +| local_dataflow.rb:165:9:165:17 | self | local_dataflow.rb:167:9:167:17 | self | +| local_dataflow.rb:165:9:165:17 | self | local_dataflow.rb:169:9:169:17 | self | +| local_dataflow.rb:167:9:167:17 | [post] self | local_dataflow.rb:171:9:171:17 | self | +| local_dataflow.rb:167:9:167:17 | call to source | local_dataflow.rb:166:13:167:17 | then ... | +| local_dataflow.rb:167:9:167:17 | self | local_dataflow.rb:171:9:171:17 | self | +| local_dataflow.rb:169:9:169:17 | [post] self | local_dataflow.rb:171:9:171:17 | self | +| local_dataflow.rb:169:9:169:17 | call to source | local_dataflow.rb:168:7:169:17 | else ... | +| local_dataflow.rb:169:9:169:17 | self | local_dataflow.rb:171:9:171:17 | self | +| local_dataflow.rb:171:9:171:17 | [post] self | local_dataflow.rb:173:3:173:9 | self | +| local_dataflow.rb:171:9:171:17 | call to source | local_dataflow.rb:170:7:171:17 | ensure ... | +| local_dataflow.rb:171:9:171:17 | self | local_dataflow.rb:173:3:173:9 | self | diff --git a/ruby/ql/test/library-tests/dataflow/local/Nodes.expected b/ruby/ql/test/library-tests/dataflow/local/Nodes.expected index 2ce5b9c2f237..18ce6eca2c53 100644 --- a/ruby/ql/test/library-tests/dataflow/local/Nodes.expected +++ b/ruby/ql/test/library-tests/dataflow/local/Nodes.expected @@ -21,6 +21,7 @@ ret | local_dataflow.rb:123:32:123:43 | call to puts | | local_dataflow.rb:127:3:127:8 | call to rand | | local_dataflow.rb:132:3:149:5 | if ... | +| local_dataflow.rb:173:3:173:9 | call to sink | arg | UseUseExplosion.rb:20:13:20:17 | @prop | UseUseExplosion.rb:20:13:20:23 | ... > ... | self | | UseUseExplosion.rb:20:13:20:23 | synthetic splat argument | UseUseExplosion.rb:20:13:20:23 | ... > ... | synthetic * | @@ -1524,3 +1525,36 @@ arg | local_dataflow.rb:148:5:148:10 | self | local_dataflow.rb:148:5:148:10 | call to use | self | | local_dataflow.rb:148:5:148:10 | synthetic splat argument | local_dataflow.rb:148:5:148:10 | call to use | synthetic * | | local_dataflow.rb:148:9:148:9 | x | local_dataflow.rb:148:5:148:10 | call to use | position 0 | +| local_dataflow.rb:154:9:154:21 | self | local_dataflow.rb:154:9:154:21 | call to raise | self | +| local_dataflow.rb:154:9:154:21 | synthetic splat argument | local_dataflow.rb:154:9:154:21 | call to raise | synthetic * | +| local_dataflow.rb:154:15:154:21 | "error" | local_dataflow.rb:154:9:154:21 | call to raise | position 0 | +| local_dataflow.rb:155:9:155:17 | self | local_dataflow.rb:155:9:155:17 | call to source | self | +| local_dataflow.rb:155:9:155:17 | synthetic splat argument | local_dataflow.rb:155:9:155:17 | call to source | synthetic * | +| local_dataflow.rb:155:16:155:16 | 1 | local_dataflow.rb:155:9:155:17 | call to source | position 0 | +| local_dataflow.rb:157:9:157:17 | self | local_dataflow.rb:157:9:157:17 | call to source | self | +| local_dataflow.rb:157:9:157:17 | synthetic splat argument | local_dataflow.rb:157:9:157:17 | call to source | synthetic * | +| local_dataflow.rb:157:16:157:16 | 2 | local_dataflow.rb:157:9:157:17 | call to source | position 0 | +| local_dataflow.rb:159:9:159:17 | self | local_dataflow.rb:159:9:159:17 | call to source | self | +| local_dataflow.rb:159:9:159:17 | synthetic splat argument | local_dataflow.rb:159:9:159:17 | call to source | synthetic * | +| local_dataflow.rb:159:16:159:16 | 3 | local_dataflow.rb:159:9:159:17 | call to source | position 0 | +| local_dataflow.rb:161:3:161:9 | self | local_dataflow.rb:161:3:161:9 | call to sink | self | +| local_dataflow.rb:161:3:161:9 | synthetic splat argument | local_dataflow.rb:161:3:161:9 | call to sink | synthetic * | +| local_dataflow.rb:161:8:161:8 | x | local_dataflow.rb:161:3:161:9 | call to sink | position 0 | +| local_dataflow.rb:164:9:164:21 | self | local_dataflow.rb:164:9:164:21 | call to raise | self | +| local_dataflow.rb:164:9:164:21 | synthetic splat argument | local_dataflow.rb:164:9:164:21 | call to raise | synthetic * | +| local_dataflow.rb:164:15:164:21 | "error" | local_dataflow.rb:164:9:164:21 | call to raise | position 0 | +| local_dataflow.rb:165:9:165:17 | self | local_dataflow.rb:165:9:165:17 | call to source | self | +| local_dataflow.rb:165:9:165:17 | synthetic splat argument | local_dataflow.rb:165:9:165:17 | call to source | synthetic * | +| local_dataflow.rb:165:16:165:16 | 4 | local_dataflow.rb:165:9:165:17 | call to source | position 0 | +| local_dataflow.rb:167:9:167:17 | self | local_dataflow.rb:167:9:167:17 | call to source | self | +| local_dataflow.rb:167:9:167:17 | synthetic splat argument | local_dataflow.rb:167:9:167:17 | call to source | synthetic * | +| local_dataflow.rb:167:16:167:16 | 5 | local_dataflow.rb:167:9:167:17 | call to source | position 0 | +| local_dataflow.rb:169:9:169:17 | self | local_dataflow.rb:169:9:169:17 | call to source | self | +| local_dataflow.rb:169:9:169:17 | synthetic splat argument | local_dataflow.rb:169:9:169:17 | call to source | synthetic * | +| local_dataflow.rb:169:16:169:16 | 6 | local_dataflow.rb:169:9:169:17 | call to source | position 0 | +| local_dataflow.rb:171:9:171:17 | self | local_dataflow.rb:171:9:171:17 | call to source | self | +| local_dataflow.rb:171:9:171:17 | synthetic splat argument | local_dataflow.rb:171:9:171:17 | call to source | synthetic * | +| local_dataflow.rb:171:16:171:16 | 7 | local_dataflow.rb:171:9:171:17 | call to source | position 0 | +| local_dataflow.rb:173:3:173:9 | self | local_dataflow.rb:173:3:173:9 | call to sink | self | +| local_dataflow.rb:173:3:173:9 | synthetic splat argument | local_dataflow.rb:173:3:173:9 | call to sink | synthetic * | +| local_dataflow.rb:173:8:173:8 | y | local_dataflow.rb:173:3:173:9 | call to sink | position 0 | diff --git a/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected b/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected index 353edd203f95..028746bbcdca 100644 --- a/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected +++ b/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected @@ -2951,9 +2951,9 @@ | local_dataflow.rb:1:1:7:3 | self (foo) | local_dataflow.rb:3:8:3:10 | self | | local_dataflow.rb:1:1:7:3 | self in foo | local_dataflow.rb:1:1:7:3 | self (foo) | | local_dataflow.rb:1:1:7:3 | synthetic splat parameter | local_dataflow.rb:1:9:1:9 | a | -| local_dataflow.rb:1:1:150:3 | x | local_dataflow.rb:10:9:10:9 | x | -| local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self | -| local_dataflow.rb:1:1:150:3 | self in local_dataflow.rb | local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | +| local_dataflow.rb:1:1:174:4 | x | local_dataflow.rb:10:9:10:9 | x | +| local_dataflow.rb:1:1:174:4 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self | +| local_dataflow.rb:1:1:174:4 | self in local_dataflow.rb | local_dataflow.rb:1:1:174:4 | self (local_dataflow.rb) | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:1:9:1:9 | a | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:2:7:2:7 | a | | local_dataflow.rb:2:3:2:3 | b | local_dataflow.rb:3:13:3:13 | b | @@ -3474,3 +3474,43 @@ | local_dataflow.rb:147:9:147:9 | [post] x | local_dataflow.rb:148:9:148:9 | x | | local_dataflow.rb:147:9:147:9 | x | local_dataflow.rb:148:9:148:9 | x | | local_dataflow.rb:148:5:148:10 | call to use | local_dataflow.rb:132:12:148:10 | then ... | +| local_dataflow.rb:152:1:174:3 | self (begin_expr) | local_dataflow.rb:154:9:154:21 | self | +| local_dataflow.rb:152:1:174:3 | self (begin_expr) | local_dataflow.rb:155:9:155:17 | self | +| local_dataflow.rb:152:1:174:3 | self in begin_expr | local_dataflow.rb:152:1:174:3 | self (begin_expr) | +| local_dataflow.rb:152:1:174:3 | synthetic splat parameter | local_dataflow.rb:152:16:152:16 | r | +| local_dataflow.rb:152:16:152:16 | r | local_dataflow.rb:152:16:152:16 | r | +| local_dataflow.rb:152:16:152:16 | r | local_dataflow.rb:154:26:154:26 | r | +| local_dataflow.rb:153:3:153:3 | x | local_dataflow.rb:161:8:161:8 | x | +| local_dataflow.rb:154:9:154:21 | [post] self | local_dataflow.rb:157:9:157:17 | self | +| local_dataflow.rb:154:9:154:21 | self | local_dataflow.rb:157:9:157:17 | self | +| local_dataflow.rb:154:26:154:26 | r | local_dataflow.rb:164:26:164:26 | r | +| local_dataflow.rb:155:9:155:17 | [post] self | local_dataflow.rb:157:9:157:17 | self | +| local_dataflow.rb:155:9:155:17 | [post] self | local_dataflow.rb:159:9:159:17 | self | +| local_dataflow.rb:155:9:155:17 | self | local_dataflow.rb:157:9:157:17 | self | +| local_dataflow.rb:155:9:155:17 | self | local_dataflow.rb:159:9:159:17 | self | +| local_dataflow.rb:157:9:157:17 | [post] self | local_dataflow.rb:159:9:159:17 | self | +| local_dataflow.rb:157:9:157:17 | call to source | local_dataflow.rb:156:13:157:17 | then ... | +| local_dataflow.rb:157:9:157:17 | self | local_dataflow.rb:159:9:159:17 | self | +| local_dataflow.rb:159:9:159:17 | [post] self | local_dataflow.rb:161:3:161:9 | self | +| local_dataflow.rb:159:9:159:17 | call to source | local_dataflow.rb:158:7:159:17 | ensure ... | +| local_dataflow.rb:159:9:159:17 | self | local_dataflow.rb:161:3:161:9 | self | +| local_dataflow.rb:161:3:161:9 | [post] self | local_dataflow.rb:164:9:164:21 | self | +| local_dataflow.rb:161:3:161:9 | [post] self | local_dataflow.rb:165:9:165:17 | self | +| local_dataflow.rb:161:3:161:9 | self | local_dataflow.rb:164:9:164:21 | self | +| local_dataflow.rb:161:3:161:9 | self | local_dataflow.rb:165:9:165:17 | self | +| local_dataflow.rb:163:3:163:3 | y | local_dataflow.rb:173:8:173:8 | y | +| local_dataflow.rb:164:9:164:21 | [post] self | local_dataflow.rb:167:9:167:17 | self | +| local_dataflow.rb:164:9:164:21 | self | local_dataflow.rb:167:9:167:17 | self | +| local_dataflow.rb:165:9:165:17 | [post] self | local_dataflow.rb:167:9:167:17 | self | +| local_dataflow.rb:165:9:165:17 | [post] self | local_dataflow.rb:169:9:169:17 | self | +| local_dataflow.rb:165:9:165:17 | self | local_dataflow.rb:167:9:167:17 | self | +| local_dataflow.rb:165:9:165:17 | self | local_dataflow.rb:169:9:169:17 | self | +| local_dataflow.rb:167:9:167:17 | [post] self | local_dataflow.rb:171:9:171:17 | self | +| local_dataflow.rb:167:9:167:17 | call to source | local_dataflow.rb:166:13:167:17 | then ... | +| local_dataflow.rb:167:9:167:17 | self | local_dataflow.rb:171:9:171:17 | self | +| local_dataflow.rb:169:9:169:17 | [post] self | local_dataflow.rb:171:9:171:17 | self | +| local_dataflow.rb:169:9:169:17 | call to source | local_dataflow.rb:168:7:169:17 | else ... | +| local_dataflow.rb:169:9:169:17 | self | local_dataflow.rb:171:9:171:17 | self | +| local_dataflow.rb:171:9:171:17 | [post] self | local_dataflow.rb:173:3:173:9 | self | +| local_dataflow.rb:171:9:171:17 | call to source | local_dataflow.rb:170:7:171:17 | ensure ... | +| local_dataflow.rb:171:9:171:17 | self | local_dataflow.rb:173:3:173:9 | self | diff --git a/ruby/ql/test/library-tests/dataflow/local/local_dataflow.rb b/ruby/ql/test/library-tests/dataflow/local/local_dataflow.rb index 6adff401655b..c58c61122d69 100644 --- a/ruby/ql/test/library-tests/dataflow/local/local_dataflow.rb +++ b/ruby/ql/test/library-tests/dataflow/local/local_dataflow.rb @@ -147,4 +147,28 @@ def use_use_madness use(x) use(x) end -end \ No newline at end of file +end + +def begin_expr r + x = begin + raise "error" if r + source(1) + rescue + source(2) + ensure + source(3) + end + sink(x) # $ MISSING: hasValueFlow=1 hasValueFlow=2 + + y = begin + raise "error" if r + source(4) + rescue + source(5) + else + source(6) + ensure + source(7) + end + sink(y) # $ MISSING: hasValueFlow=5 hasValueFlow=6 +end