From ea1c7b51efc143be93e9e7d4420590022cc46af9 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 5 May 2021 20:34:08 +0200 Subject: [PATCH 1/4] Add more operator assignment tests --- ql/test/library-tests/ast/Ast.expected | 34 ++++ .../library-tests/ast/calls/calls.expected | 14 ++ ql/test/library-tests/ast/calls/calls.rb | 1 + .../ast/operations/assignment.expected | 12 ++ .../ast/operations/operation.expected | 12 ++ .../ast/operations/operations.rb | 13 +- .../controlflow/graph/Cfg.expected | 171 ++++++++++++++++++ .../controlflow/graph/desugar.rb | 22 +++ 8 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 ql/test/library-tests/controlflow/graph/desugar.rb diff --git a/ql/test/library-tests/ast/Ast.expected b/ql/test/library-tests/ast/Ast.expected index 7f5e877af1c..ff9b6cb5dae 100644 --- a/ql/test/library-tests/ast/Ast.expected +++ b/ql/test/library-tests/ast/Ast.expected @@ -567,6 +567,21 @@ calls/calls.rb: # 319| getReceiver: [Self] self # 319| getArgument: [IntegerLiteral] 0 # 319| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 320| getStmt: [AssignMulExpr] ... *= ... +# 320| getAnOperand/getLeftOperand: [ElementReference, SetterMethodCall] ...[...] +# 320| getReceiver: [MethodCall] call to bar +# 320| getReceiver: [MethodCall] call to foo +# 320| getReceiver: [Self] self +# 320| getArgument: [IntegerLiteral] 0 +# 320| getArgument: [MethodCall] call to baz +# 320| getReceiver: [MethodCall] call to foo +# 320| getReceiver: [Self] self +# 320| getArgument: [AddExpr] ... + ... +# 320| getAnOperand/getLeftOperand: [MethodCall] call to boo +# 320| getReceiver: [MethodCall] call to foo +# 320| getReceiver: [Self] self +# 320| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 320| getAnOperand/getRightOperand: [IntegerLiteral] 2 control/cases.rb: # 1| [Toplevel] cases.rb # 2| getStmt: [AssignExpr] ... = ... @@ -1718,6 +1733,25 @@ operations/operations.rb: # 84| getStmt: [AssignBitwiseXorExpr] ... ^= ... # 84| getAnOperand/getLeftOperand: [LocalVariableAccess] baz # 84| getAnOperand/getRightOperand: [LocalVariableAccess] qux +# 86| getStmt: [ClassDeclaration] X +# 87| getStmt: [AssignExpr] ... = ... +# 87| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x +# 87| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 88| getStmt: [AssignAddExpr] ... += ... +# 88| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x +# 88| getAnOperand/getRightOperand: [IntegerLiteral] 2 +# 90| getStmt: [AssignExpr] ... = ... +# 90| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y +# 90| getAnOperand/getRightOperand: [IntegerLiteral] 3 +# 91| getStmt: [AssignDivExpr] ... /= ... +# 91| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y +# 91| getAnOperand/getRightOperand: [IntegerLiteral] 4 +# 94| getStmt: [AssignExpr] ... = ... +# 94| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var +# 94| getAnOperand/getRightOperand: [IntegerLiteral] 5 +# 95| getStmt: [AssignMulExpr] ... *= ... +# 95| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var +# 95| getAnOperand/getRightOperand: [IntegerLiteral] 6 params/params.rb: # 1| [Toplevel] params.rb # 4| getStmt: [Method] identifier_method_params diff --git a/ql/test/library-tests/ast/calls/calls.expected b/ql/test/library-tests/ast/calls/calls.expected index 74bcfee07ed..e10de4ae3d5 100644 --- a/ql/test/library-tests/ast/calls/calls.expected +++ b/ql/test/library-tests/ast/calls/calls.expected @@ -36,6 +36,12 @@ callsWithArguments | calls.rb:317:5:317:10 | ...[...] | []= | 0 | calls.rb:317:9:317:9 | 5 | | calls.rb:319:1:319:6 | ...[...] | [] | 0 | calls.rb:319:5:319:5 | 0 | | calls.rb:319:1:319:6 | ...[...] | []= | 0 | calls.rb:319:5:319:5 | 0 | +| calls.rb:320:1:320:32 | ...[...] | [] | 0 | calls.rb:320:9:320:9 | 0 | +| calls.rb:320:1:320:32 | ...[...] | [] | 1 | calls.rb:320:12:320:18 | call to baz | +| calls.rb:320:1:320:32 | ...[...] | [] | 2 | calls.rb:320:21:320:31 | ... + ... | +| calls.rb:320:1:320:32 | ...[...] | []= | 0 | calls.rb:320:9:320:9 | 0 | +| calls.rb:320:1:320:32 | ...[...] | []= | 1 | calls.rb:320:12:320:18 | call to baz | +| calls.rb:320:1:320:32 | ...[...] | []= | 2 | calls.rb:320:21:320:31 | ... + ... | callsWithReceiver | calls.rb:2:1:2:5 | call to foo | calls.rb:2:1:2:5 | self | | calls.rb:5:1:5:10 | call to bar | calls.rb:5:1:5:3 | Foo | @@ -216,6 +222,13 @@ callsWithReceiver | calls.rb:318:1:318:10 | call to count/count= | calls.rb:318:1:318:4 | self | | calls.rb:319:1:319:3 | call to foo | calls.rb:319:1:319:3 | self | | calls.rb:319:1:319:6 | ...[...] | calls.rb:319:1:319:3 | call to foo | +| calls.rb:320:1:320:3 | call to foo | calls.rb:320:1:320:3 | self | +| calls.rb:320:1:320:7 | call to bar | calls.rb:320:1:320:3 | call to foo | +| calls.rb:320:1:320:32 | ...[...] | calls.rb:320:1:320:7 | call to bar | +| calls.rb:320:12:320:14 | call to foo | calls.rb:320:12:320:14 | self | +| calls.rb:320:12:320:18 | call to baz | calls.rb:320:12:320:14 | call to foo | +| calls.rb:320:21:320:23 | call to foo | calls.rb:320:21:320:23 | self | +| calls.rb:320:21:320:27 | call to boo | calls.rb:320:21:320:23 | call to foo | callsWithBlock | calls.rb:17:1:17:17 | call to foo | calls.rb:17:5:17:17 | { ... } | | calls.rb:20:1:22:3 | call to foo | calls.rb:20:5:22:3 | do ... end | @@ -262,3 +275,4 @@ setterCalls | calls.rb:317:5:317:10 | ...[...] | | calls.rb:318:1:318:10 | call to count/count= | | calls.rb:319:1:319:6 | ...[...] | +| calls.rb:320:1:320:32 | ...[...] | diff --git a/ql/test/library-tests/ast/calls/calls.rb b/ql/test/library-tests/ast/calls/calls.rb index 8b827d07f9b..1362b043e8a 100644 --- a/ql/test/library-tests/ast/calls/calls.rb +++ b/ql/test/library-tests/ast/calls/calls.rb @@ -317,3 +317,4 @@ self.foo, *self.bar, foo[4] = [1, 2, 3, 4] a, *foo[5] = [1, 2, 3] self.count += 1 foo[0] += 1 +foo.bar[0, foo.baz, foo.boo + 1] *= 2 diff --git a/ql/test/library-tests/ast/operations/assignment.expected b/ql/test/library-tests/ast/operations/assignment.expected index d1f34896b31..454f86743ba 100644 --- a/ql/test/library-tests/ast/operations/assignment.expected +++ b/ql/test/library-tests/ast/operations/assignment.expected @@ -30,6 +30,12 @@ assignments | operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:2:82:4 | foo | operations.rb:82:9:82:12 | mask | AssignBitwiseAndExpr | | operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:2:83:4 | bar | operations.rb:83:9:83:12 | 0x01 | AssignBitwiseOrExpr | | operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:2:84:4 | baz | operations.rb:84:9:84:11 | qux | AssignBitwiseXorExpr | +| operations.rb:87:3:87:8 | ... = ... | = | operations.rb:87:3:87:4 | @x | operations.rb:87:8:87:8 | 1 | AssignExpr | +| operations.rb:88:3:88:9 | ... += ... | += | operations.rb:88:3:88:4 | @x | operations.rb:88:9:88:9 | 2 | AssignAddExpr | +| operations.rb:90:3:90:9 | ... = ... | = | operations.rb:90:3:90:5 | @@y | operations.rb:90:9:90:9 | 3 | AssignExpr | +| operations.rb:91:3:91:10 | ... /= ... | /= | operations.rb:91:3:91:5 | @@y | operations.rb:91:10:91:10 | 4 | AssignDivExpr | +| operations.rb:94:1:94:15 | ... = ... | = | operations.rb:94:1:94:11 | $global_var | operations.rb:94:15:94:15 | 5 | AssignExpr | +| operations.rb:95:1:95:16 | ... *= ... | *= | operations.rb:95:1:95:11 | $global_var | operations.rb:95:16:95:16 | 6 | AssignMulExpr | assignOperations | operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:1:68:1 | x | operations.rb:68:6:68:8 | 128 | AssignAddExpr | | operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:1:69:1 | y | operations.rb:69:6:69:7 | 32 | AssignSubExpr | @@ -44,6 +50,9 @@ assignOperations | operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:2:82:4 | foo | operations.rb:82:9:82:12 | mask | AssignBitwiseAndExpr | | operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:2:83:4 | bar | operations.rb:83:9:83:12 | 0x01 | AssignBitwiseOrExpr | | operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:2:84:4 | baz | operations.rb:84:9:84:11 | qux | AssignBitwiseXorExpr | +| operations.rb:88:3:88:9 | ... += ... | += | operations.rb:88:3:88:4 | @x | operations.rb:88:9:88:9 | 2 | AssignAddExpr | +| operations.rb:91:3:91:10 | ... /= ... | /= | operations.rb:91:3:91:5 | @@y | operations.rb:91:10:91:10 | 4 | AssignDivExpr | +| operations.rb:95:1:95:16 | ... *= ... | *= | operations.rb:95:1:95:11 | $global_var | operations.rb:95:16:95:16 | 6 | AssignMulExpr | assignArithmeticOperations | operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:1:68:1 | x | operations.rb:68:6:68:8 | 128 | AssignAddExpr | | operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:1:69:1 | y | operations.rb:69:6:69:7 | 32 | AssignSubExpr | @@ -51,6 +60,9 @@ assignArithmeticOperations | operations.rb:71:1:71:6 | ... /= ... | /= | operations.rb:71:1:71:1 | b | operations.rb:71:6:71:6 | 4 | AssignDivExpr | | operations.rb:72:1:72:6 | ... %= ... | %= | operations.rb:72:1:72:1 | z | operations.rb:72:6:72:6 | 2 | AssignModuloExpr | | operations.rb:73:1:73:11 | ... **= ... | **= | operations.rb:73:1:73:3 | foo | operations.rb:73:9:73:11 | bar | AssignExponentExpr | +| operations.rb:88:3:88:9 | ... += ... | += | operations.rb:88:3:88:4 | @x | operations.rb:88:9:88:9 | 2 | AssignAddExpr | +| operations.rb:91:3:91:10 | ... /= ... | /= | operations.rb:91:3:91:5 | @@y | operations.rb:91:10:91:10 | 4 | AssignDivExpr | +| operations.rb:95:1:95:16 | ... *= ... | *= | operations.rb:95:1:95:11 | $global_var | operations.rb:95:16:95:16 | 6 | AssignMulExpr | assignLogicalOperations | operations.rb:76:2:76:8 | ... &&= ... | &&= | operations.rb:76:2:76:2 | x | operations.rb:76:8:76:8 | y | AssignLogicalAndExpr | | operations.rb:77:2:77:8 | ... \|\|= ... | \|\|= | operations.rb:77:2:77:2 | a | operations.rb:77:8:77:8 | b | AssignLogicalOrExpr | diff --git a/ql/test/library-tests/ast/operations/operation.expected b/ql/test/library-tests/ast/operations/operation.expected index 3d5346e6346..7f4d25068eb 100644 --- a/ql/test/library-tests/ast/operations/operation.expected +++ b/ql/test/library-tests/ast/operations/operation.expected @@ -116,3 +116,15 @@ | operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:9:83:12 | 0x01 | AssignBitwiseOrExpr | | operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:2:84:4 | baz | AssignBitwiseXorExpr | | operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:9:84:11 | qux | AssignBitwiseXorExpr | +| operations.rb:87:3:87:8 | ... = ... | = | operations.rb:87:3:87:4 | @x | AssignExpr | +| operations.rb:87:3:87:8 | ... = ... | = | operations.rb:87:8:87:8 | 1 | AssignExpr | +| operations.rb:88:3:88:9 | ... += ... | += | operations.rb:88:3:88:4 | @x | AssignAddExpr | +| operations.rb:88:3:88:9 | ... += ... | += | operations.rb:88:9:88:9 | 2 | AssignAddExpr | +| operations.rb:90:3:90:9 | ... = ... | = | operations.rb:90:3:90:5 | @@y | AssignExpr | +| operations.rb:90:3:90:9 | ... = ... | = | operations.rb:90:9:90:9 | 3 | AssignExpr | +| operations.rb:91:3:91:10 | ... /= ... | /= | operations.rb:91:3:91:5 | @@y | AssignDivExpr | +| operations.rb:91:3:91:10 | ... /= ... | /= | operations.rb:91:10:91:10 | 4 | AssignDivExpr | +| operations.rb:94:1:94:15 | ... = ... | = | operations.rb:94:1:94:11 | $global_var | AssignExpr | +| operations.rb:94:1:94:15 | ... = ... | = | operations.rb:94:15:94:15 | 5 | AssignExpr | +| operations.rb:95:1:95:16 | ... *= ... | *= | operations.rb:95:1:95:11 | $global_var | AssignMulExpr | +| operations.rb:95:1:95:16 | ... *= ... | *= | operations.rb:95:16:95:16 | 6 | AssignMulExpr | diff --git a/ql/test/library-tests/ast/operations/operations.rb b/ql/test/library-tests/ast/operations/operations.rb index 707a2d36425..effee5860ba 100644 --- a/ql/test/library-tests/ast/operations/operations.rb +++ b/ql/test/library-tests/ast/operations/operations.rb @@ -81,4 +81,15 @@ foo **= bar y >>= 3 foo &= mask bar |= 0x01 - baz ^= qux \ No newline at end of file + baz ^= qux + +class X + @x = 1 + @x += 2 + + @@y = 3 + @@y /= 4 +end + +$global_var = 5 +$global_var *= 6 diff --git a/ql/test/library-tests/controlflow/graph/Cfg.expected b/ql/test/library-tests/controlflow/graph/Cfg.expected index 3e39856c559..84e66808854 100644 --- a/ql/test/library-tests/controlflow/graph/Cfg.expected +++ b/ql/test/library-tests/controlflow/graph/Cfg.expected @@ -2083,6 +2083,177 @@ cfg.rb: # 194| x #-----| -> call to puts +desugar.rb: +# 1| enter m1 +#-----| -> x + +# 1| enter desugar.rb +#-----| -> m1 + +# 1| m1 +#-----| -> m2 + +# 1| exit m1 + +# 1| exit desugar.rb + +# 1| exit m1 (normal) +#-----| -> exit m1 + +# 1| exit desugar.rb (normal) +#-----| -> exit desugar.rb + +# 1| x +#-----| -> x + +# 2| ... += ... +#-----| -> exit m1 (normal) + +# 2| x +#-----| -> 1 + +# 2| 1 +#-----| -> ... += ... + +# 5| enter m2 +#-----| -> x + +# 5| m2 +#-----| -> m3 + +# 5| exit m2 + +# 5| exit m2 (normal) +#-----| -> exit m2 + +# 5| x +#-----| -> x + +# 6| ... += ... +#-----| -> exit m2 (normal) + +# 6| call to count/count= +#-----| -> 1 + +# 6| call to foo +#-----| -> call to count/count= + +# 6| x +#-----| -> call to foo + +# 6| 1 +#-----| -> ... += ... + +# 9| enter m3 +#-----| -> x + +# 9| m3 +#-----| -> X + +# 9| exit m3 + +# 9| exit m3 (normal) +#-----| -> exit m3 + +# 9| x +#-----| -> y + +# 9| y +#-----| -> x + +# 10| ... += ... +#-----| -> exit m3 (normal) + +# 10| ...[...] +#-----| -> 1 + +# 10| call to foo +#-----| -> 0 + +# 10| x +#-----| -> call to foo + +# 10| 0 +#-----| -> y + +# 10| call to bar +#-----| -> x + +# 10| y +#-----| -> call to bar + +# 10| ... + ... +#-----| -> ...[...] + +# 10| call to baz +#-----| -> 3 + +# 10| x +#-----| -> call to baz + +# 10| 3 +#-----| -> ... + ... + +# 10| 1 +#-----| -> ... += ... + +# 13| X +#-----| -> @x + +# 14| ... = ... +#-----| -> @x + +# 14| @x +#-----| -> 1 + +# 14| 1 +#-----| -> ... = ... + +# 15| ... += ... +#-----| -> @@y + +# 15| @x +#-----| -> 2 + +# 15| 2 +#-----| -> ... += ... + +# 17| ... = ... +#-----| -> @@y + +# 17| @@y +#-----| -> 3 + +# 17| 3 +#-----| -> ... = ... + +# 18| ... /= ... +#-----| -> $global_var + +# 18| @@y +#-----| -> 4 + +# 18| 4 +#-----| -> ... /= ... + +# 21| ... = ... +#-----| -> $global_var + +# 21| $global_var +#-----| -> 5 + +# 21| 5 +#-----| -> ... = ... + +# 22| ... *= ... +#-----| -> exit desugar.rb (normal) + +# 22| $global_var +#-----| -> 6 + +# 22| 6 +#-----| -> ... *= ... + exit.rb: # 1| enter m1 #-----| -> x diff --git a/ql/test/library-tests/controlflow/graph/desugar.rb b/ql/test/library-tests/controlflow/graph/desugar.rb new file mode 100644 index 00000000000..25dd0e48e0e --- /dev/null +++ b/ql/test/library-tests/controlflow/graph/desugar.rb @@ -0,0 +1,22 @@ +def m1 x + x += 1 +end + +def m2 x + x.foo.count += 1 +end + +def m3 x, y + x.foo[0, y.bar, x.baz + 3] += 1 +end + +class X + @x = 1 + @x += 2 + + @@y = 3 + @@y /= 4 +end + +$global_var = 5 +$global_var *= 6 From ff06e724b1c5dbe281008f57324db4ea4922108d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 12 May 2021 16:28:35 +0200 Subject: [PATCH 2/4] AST synthesis framework --- ql/consistency-queries/AstConsistency.ql | 12 +- ql/src/codeql_ruby/AST.qll | 29 +- ql/src/codeql_ruby/ast/Call.qll | 9 +- ql/src/codeql_ruby/ast/Expr.qll | 14 +- ql/src/codeql_ruby/ast/Operation.qll | 94 +++++- ql/src/codeql_ruby/ast/Parameter.qll | 19 +- ql/src/codeql_ruby/ast/Pattern.qll | 8 +- ql/src/codeql_ruby/ast/Variable.qll | 67 +---- ql/src/codeql_ruby/ast/internal/AST.qll | 267 ++++++++++++++---- ql/src/codeql_ruby/ast/internal/Module.qll | 4 +- ql/src/codeql_ruby/ast/internal/Synthesis.qll | 173 ++++++++++++ ql/src/codeql_ruby/ast/internal/Variable.qll | 164 ++++++++++- ql/src/codeql_ruby/controlflow/CfgNodes.qll | 11 +- .../codeql_ruby/controlflow/internal/Cfg.ql | 28 -- .../codeql_ruby/controlflow/internal/Cfg.qll | 32 +++ .../internal/ControlFlowGraphImpl.qll | 21 ++ ql/src/codeql_ruby/printAst.qll | 36 ++- ql/test/library-tests/ast/Ast.ql | 1 - ql/test/library-tests/ast/AstDesugar.expected | 180 ++++++++++++ ql/test/library-tests/ast/AstDesugar.ql | 9 + .../ast/operations/assignment.expected | 16 ++ .../ast/operations/binary.expected | 32 +++ .../ast/operations/operation.expected | 64 +++++ .../controlflow/graph/Cfg.expected | 118 ++++++-- .../library-tests/controlflow/graph/Cfg.ql | 9 + .../library-tests/controlflow/graph/Cfg.qlref | 1 - .../dataflow/local/DataflowStep.expected | 5 +- ql/test/library-tests/variables/ssa.expected | 46 +-- .../variables/varaccess.expected | 16 +- 29 files changed, 1235 insertions(+), 250 deletions(-) create mode 100644 ql/src/codeql_ruby/ast/internal/Synthesis.qll delete mode 100644 ql/src/codeql_ruby/controlflow/internal/Cfg.ql create mode 100644 ql/src/codeql_ruby/controlflow/internal/Cfg.qll create mode 100644 ql/test/library-tests/ast/AstDesugar.expected create mode 100644 ql/test/library-tests/ast/AstDesugar.ql create mode 100644 ql/test/library-tests/controlflow/graph/Cfg.ql delete mode 100644 ql/test/library-tests/controlflow/graph/Cfg.qlref diff --git a/ql/consistency-queries/AstConsistency.ql b/ql/consistency-queries/AstConsistency.ql index 6977374b5ed..beb4e08fb76 100644 --- a/ql/consistency-queries/AstConsistency.ql +++ b/ql/consistency-queries/AstConsistency.ql @@ -15,6 +15,14 @@ query predicate missingParent(AstNode node, string cls) { query predicate multipleParents(AstNode node, AstNode parent, string cls) { parent = node.getParent() and - count(node.getParent()) > 1 and - cls = getAPrimaryQlClass(parent) + cls = getAPrimaryQlClass(parent) and + exists(AstNode one, AstNode two | + one = node.getParent() and + two = node.getParent() and + one != two + | + one.isSynthesized() and two.isSynthesized() + or + not one.isSynthesized() and not two.isSynthesized() + ) } diff --git a/ql/src/codeql_ruby/AST.qll b/ql/src/codeql_ruby/AST.qll index 0c895478ddf..26b37c2d192 100644 --- a/ql/src/codeql_ruby/AST.qll +++ b/ql/src/codeql_ruby/AST.qll @@ -14,6 +14,7 @@ import ast.Statement import ast.Variable private import ast.internal.AST private import ast.internal.Scope +private import ast.internal.Synthesis /** * A node in the abstract syntax tree. This class is the base class for all Ruby @@ -56,7 +57,11 @@ class AstNode extends TAstNode { final AstNode getAChild() { result = this.getAChild(_) } /** Gets the parent of this `AstNode`, if this node is not a root node. */ - final AstNode getParent() { result.getAChild() = this } + final AstNode getParent() { + result.getAChild() = this + or + result.getAChild().getDesugared() = this + } /** * Gets a child of this node, which can also be retrieved using a predicate @@ -75,5 +80,25 @@ class AstNode extends TAstNode { * foo(123) * ``` */ - predicate isSynthesized() { this instanceof TImplicitSelf } + final predicate isSynthesized() { this = getSynthChild(_, _) } + + /** + * Gets the desugared version of this AST node, if any. + * + * For example, the desugared version of + * + * ```rb + * x += y + * ``` + * + * is + * + * ```rb + * x = x + y + * ``` + * + * when `x` is a variable. Whenever an AST node can be desugared, + * then the desugared version is used in the control-flow graph. + */ + final AstNode getDesugared() { result = getSynthChild(this, -1) } } diff --git a/ql/src/codeql_ruby/ast/Call.qll b/ql/src/codeql_ruby/ast/Call.qll index b65a26a22c5..7c5ae5a7893 100644 --- a/ql/src/codeql_ruby/ast/Call.qll +++ b/ql/src/codeql_ruby/ast/Call.qll @@ -137,7 +137,7 @@ private class IdentifierMethodCall extends MethodCall, TIdentifierMethodCall { final override string getMethodName() { result = getMethodName(this, g.getValue()) } - final override Self getReceiver() { result = TImplicitSelf(g) } + final override Self getReceiver() { result = TSelfSynth(this, 0) } } private class ScopeResolutionMethodCall extends MethodCall, TScopeResolutionMethodCall { @@ -162,12 +162,7 @@ private class RegularMethodCall extends MethodCall, TRegularMethodCall { not exists(g.getReceiver()) and toGenerated(result) = g.getMethod().(Generated::ScopeResolution).getScope() or - // If there's no explicit receiver (or scope resolution that acts like a - // receiver), then the receiver is implicitly `self`. N.B. `::Foo()` is - // not valid Ruby. - not exists(g.getReceiver()) and - not exists(g.getMethod().(Generated::ScopeResolution).getScope()) and - result = TImplicitSelf(g) + result = TSelfSynth(this, 0) } final override string getMethodName() { diff --git a/ql/src/codeql_ruby/ast/Expr.qll b/ql/src/codeql_ruby/ast/Expr.qll index 59bd9335a8c..17b52b97268 100644 --- a/ql/src/codeql_ruby/ast/Expr.qll +++ b/ql/src/codeql_ruby/ast/Expr.qll @@ -206,17 +206,23 @@ class BodyStmt extends StmtSequence, TBodyStmt { * ``` */ class ParenthesizedExpr extends StmtSequence, TParenthesizedExpr { - private Generated::ParenthesizedStatements g; - - ParenthesizedExpr() { this = TParenthesizedExpr(g) } - final override string getAPrimaryQlClass() { result = "ParenthesizedExpr" } final override string toString() { result = "( ... )" } +} + +private class ParenthesizedExprReal extends ParenthesizedExpr, TParenthesizedExprReal { + private Generated::ParenthesizedStatements g; + + ParenthesizedExprReal() { this = TParenthesizedExprReal(g) } final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) } } +private class ParenthesizedExprSynth extends ParenthesizedExpr, TParenthesizedExprSynth { + final override Stmt getStmt(int n) { synthChild(this, n, result) } +} + /** * A pair expression. For example, in a hash: * ```rb diff --git a/ql/src/codeql_ruby/ast/Operation.qll b/ql/src/codeql_ruby/ast/Operation.qll index b5acf8c8116..7b4394cc45e 100644 --- a/ql/src/codeql_ruby/ast/Operation.qll +++ b/ql/src/codeql_ruby/ast/Operation.qll @@ -101,12 +101,6 @@ class DefinedExpr extends UnaryOperation, TDefinedExpr { /** A binary operation. */ class BinaryOperation extends Operation, TBinaryOperation { - private Generated::Binary g; - - BinaryOperation() { g = toGenerated(this) } - - final override string getOperator() { result = g.getOperator() } - final override Expr getAnOperand() { result = this.getLeftOperand() or result = this.getRightOperand() } @@ -122,10 +116,28 @@ class BinaryOperation extends Operation, TBinaryOperation { } /** Gets the left operand of this binary operation. */ - final Stmt getLeftOperand() { toGenerated(result) = g.getLeft() } + Stmt getLeftOperand() { none() } /** Gets the right operand of this binary operation. */ - final Stmt getRightOperand() { toGenerated(result) = g.getRight() } + Stmt getRightOperand() { none() } +} + +private class BinaryOperationReal extends BinaryOperation { + private Generated::Binary g; + + BinaryOperationReal() { g = toGenerated(this) } + + final override string getOperator() { result = g.getOperator() } + + final override Stmt getLeftOperand() { toGenerated(result) = g.getLeft() } + + final override Stmt getRightOperand() { toGenerated(result) = g.getRight() } +} + +abstract private class BinaryOperationSynth extends BinaryOperation { + final override Stmt getLeftOperand() { synthChild(this, 0, result) } + + final override Stmt getRightOperand() { synthChild(this, 1, result) } } /** @@ -143,6 +155,10 @@ class AddExpr extends BinaryArithmeticOperation, TAddExpr { final override string getAPrimaryQlClass() { result = "AddExpr" } } +private class AddExprSynth extends AddExpr, BinaryOperationSynth, TAddExprSynth { + final override string getOperator() { result = "+" } +} + /** * A subtract expression. * ```rb @@ -153,6 +169,10 @@ class SubExpr extends BinaryArithmeticOperation, TSubExpr { final override string getAPrimaryQlClass() { result = "SubExpr" } } +private class SubExprSynth extends SubExpr, BinaryOperationSynth, TSubExprSynth { + final override string getOperator() { result = "-" } +} + /** * A multiply expression. * ```rb @@ -163,6 +183,10 @@ class MulExpr extends BinaryArithmeticOperation, TMulExpr { final override string getAPrimaryQlClass() { result = "MulExpr" } } +private class MulExprSynth extends MulExpr, BinaryOperationSynth, TMulExprSynth { + final override string getOperator() { result = "*" } +} + /** * A divide expression. * ```rb @@ -173,6 +197,10 @@ class DivExpr extends BinaryArithmeticOperation, TDivExpr { final override string getAPrimaryQlClass() { result = "DivExpr" } } +private class DivExprSynth extends DivExpr, BinaryOperationSynth, TDivExprSynth { + final override string getOperator() { result = "/" } +} + /** * A modulo expression. * ```rb @@ -183,6 +211,10 @@ class ModuloExpr extends BinaryArithmeticOperation, TModuloExpr { final override string getAPrimaryQlClass() { result = "ModuloExpr" } } +private class ModuloExprSynth extends ModuloExpr, BinaryOperationSynth, TModuloExprSynth { + final override string getOperator() { result = "%" } +} + /** * An exponent expression. * ```rb @@ -193,6 +225,10 @@ class ExponentExpr extends BinaryArithmeticOperation, TExponentExpr { final override string getAPrimaryQlClass() { result = "ExponentExpr" } } +private class ExponentExprSynth extends ExponentExpr, BinaryOperationSynth, TExponentExprSynth { + final override string getOperator() { result = "**" } +} + /** * A binary logical operation. */ @@ -209,6 +245,10 @@ class LogicalAndExpr extends BinaryLogicalOperation, TLogicalAndExpr { final override string getAPrimaryQlClass() { result = "LogicalAndExpr" } } +private class LogicalAndExprSynth extends LogicalAndExpr, BinaryOperationSynth, TLogicalAndExprSynth { + final override string getOperator() { result = "&&" } +} + /** * A logical OR operation, using either `or` or `||`. * ```rb @@ -220,6 +260,10 @@ class LogicalOrExpr extends BinaryLogicalOperation, TLogicalOrExpr { final override string getAPrimaryQlClass() { result = "LogicalOrExpr" } } +private class LogicalOrExprSynth extends LogicalOrExpr, BinaryOperationSynth, TLogicalOrExprSynth { + final override string getOperator() { result = "||" } +} + /** * A binary bitwise operation. */ @@ -235,6 +279,10 @@ class LShiftExpr extends BinaryBitwiseOperation, TLShiftExpr { final override string getAPrimaryQlClass() { result = "LShiftExpr" } } +private class LShiftExprSynth extends LShiftExpr, BinaryOperationSynth, TLShiftExprSynth { + final override string getOperator() { result = "<<" } +} + /** * A right-shift operation. * ```rb @@ -245,6 +293,10 @@ class RShiftExpr extends BinaryBitwiseOperation, TRShiftExpr { final override string getAPrimaryQlClass() { result = "RShiftExpr" } } +private class RShiftExprSynth extends RShiftExpr, BinaryOperationSynth, TRShiftExprSynth { + final override string getOperator() { result = ">>" } +} + /** * A bitwise AND operation. * ```rb @@ -255,6 +307,10 @@ class BitwiseAndExpr extends BinaryBitwiseOperation, TBitwiseAndExpr { final override string getAPrimaryQlClass() { result = "BitwiseAndExpr" } } +private class BitwiseAndSynthExpr extends BitwiseAndExpr, BinaryOperationSynth, TBitwiseAndExprSynth { + final override string getOperator() { result = "&" } +} + /** * A bitwise OR operation. * ```rb @@ -265,6 +321,10 @@ class BitwiseOrExpr extends BinaryBitwiseOperation, TBitwiseOrExpr { final override string getAPrimaryQlClass() { result = "BitwiseOrExpr" } } +private class BitwiseOrSynthExpr extends BitwiseOrExpr, BinaryOperationSynth, TBitwiseOrExprSynth { + final override string getOperator() { result = "|" } +} + /** * An XOR (exclusive OR) operation. * ```rb @@ -275,6 +335,10 @@ class BitwiseXorExpr extends BinaryBitwiseOperation, TBitwiseXorExpr { final override string getAPrimaryQlClass() { result = "BitwiseXorExpr" } } +private class BitwiseXorSynthExpr extends BitwiseXorExpr, BinaryOperationSynth, TBitwiseXorExprSynth { + final override string getOperator() { result = "^" } +} + /** * A comparison operation. That is, either an equality operation or a * relational operation. @@ -455,17 +519,25 @@ class Assignment extends Operation, TAssignment { * ``` */ class AssignExpr extends Assignment, TAssignExpr { + final override string getOperator() { result = "=" } + + final override string getAPrimaryQlClass() { result = "AssignExpr" } +} + +private class AssignExprReal extends AssignExpr, TAssignExprReal { private Generated::Assignment g; - AssignExpr() { this = TAssignExpr(g) } + AssignExprReal() { this = TAssignExprReal(g) } final override Pattern getLeftOperand() { toGenerated(result) = g.getLeft() } final override Expr getRightOperand() { toGenerated(result) = g.getRight() } +} - final override string getOperator() { result = "=" } +private class AssignExprSynth extends AssignExpr, TAssignExprSynth { + final override Pattern getLeftOperand() { synthChild(this, 0, result) } - override string getAPrimaryQlClass() { result = "AssignExpr" } + final override Expr getRightOperand() { synthChild(this, 1, result) } } /** diff --git a/ql/src/codeql_ruby/ast/Parameter.qll b/ql/src/codeql_ruby/ast/Parameter.qll index 7f9c11b417b..d70c8cc7588 100644 --- a/ql/src/codeql_ruby/ast/Parameter.qll +++ b/ql/src/codeql_ruby/ast/Parameter.qll @@ -37,10 +37,7 @@ class TuplePatternParameter extends PatternParameter, TuplePattern, TTuplePatter final override string getAPrimaryQlClass() { result = "TuplePatternParameter" } - override AstNode getAChild(string pred) { - result = PatternParameter.super.getAChild(pred) or - result = TuplePattern.super.getAChild(pred) - } + override AstNode getAChild(string pred) { result = TuplePattern.super.getAChild(pred) } } /** A named parameter. */ @@ -60,8 +57,6 @@ class NamedParameter extends Parameter, TNamedParameter { final VariableAccess getDefiningAccess() { result = this.getVariable().getDefiningAccess() } override AstNode getAChild(string pred) { - result = Parameter.super.getAChild(pred) - or pred = "getDefiningAccess" and result = this.getDefiningAccess() } @@ -75,7 +70,7 @@ class SimpleParameter extends NamedParameter, PatternParameter, VariablePattern, final override string getName() { result = g.getValue() } - final override LocalVariable getVariable() { result = TLocalVariable(_, _, g) } + final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g) } final override LocalVariable getAVariable() { result = this.getVariable() } @@ -99,7 +94,7 @@ class BlockParameter extends NamedParameter, TBlockParameter { final override string getName() { result = g.getName().getValue() } - final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) } + final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g.getName()) } final override string toString() { result = "&" + this.getName() } @@ -122,7 +117,7 @@ class HashSplatParameter extends NamedParameter, THashSplatParameter { final override string getAPrimaryQlClass() { result = "HashSplatParameter" } - final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) } + final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g.getName()) } final override string toString() { result = "**" + this.getName() } @@ -147,7 +142,7 @@ class KeywordParameter extends NamedParameter, TKeywordParameter { final override string getAPrimaryQlClass() { result = "KeywordParameter" } - final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) } + final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g.getName()) } /** * Gets the default value, i.e. the value assigned to the parameter when one @@ -197,7 +192,7 @@ class OptionalParameter extends NamedParameter, TOptionalParameter { */ final Expr getDefaultValue() { toGenerated(result) = g.getValue() } - final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) } + final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g.getName()) } final override string toString() { result = this.getName() } @@ -227,7 +222,7 @@ class SplatParameter extends NamedParameter, TSplatParameter { final override string getAPrimaryQlClass() { result = "SplatParameter" } - final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) } + final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g.getName()) } final override string toString() { result = "*" + this.getName() } diff --git a/ql/src/codeql_ruby/ast/Pattern.qll b/ql/src/codeql_ruby/ast/Pattern.qll index 3f5d335ec05..e6d21242196 100644 --- a/ql/src/codeql_ruby/ast/Pattern.qll +++ b/ql/src/codeql_ruby/ast/Pattern.qll @@ -7,9 +7,13 @@ private import internal.Variable /** A pattern. */ class Pattern extends AstNode { Pattern() { - explicitAssignmentNode(toGenerated(this), _) or - implicitAssignmentNode(toGenerated(this)) or + explicitAssignmentNode(toGenerated(this), _) + or + implicitAssignmentNode(toGenerated(this)) + or implicitParameterAssignmentNode(toGenerated(this), _) + or + this = getSynthChild(any(AssignExpr ae), 0) } /** Gets a variable used in (or introduced by) this pattern. */ diff --git a/ql/src/codeql_ruby/ast/Variable.qll b/ql/src/codeql_ruby/ast/Variable.qll index bc2ab278e6c..07f0f6397a7 100644 --- a/ql/src/codeql_ruby/ast/Variable.qll +++ b/ql/src/codeql_ruby/ast/Variable.qll @@ -8,21 +8,17 @@ private import internal.Variable /** A variable declared in a scope. */ class Variable extends TVariable { - Variable::Range range; - - Variable() { range = this } - /** Gets the name of this variable. */ - final string getName() { result = range.getName() } + string getName() { none() } /** Gets a textual representation of this variable. */ final string toString() { result = this.getName() } /** Gets the location of this variable. */ - final Location getLocation() { result = range.getLocation() } + Location getLocation() { none() } /** Gets the scope this variable is declared in. */ - final Scope getDeclaringScope() { toGenerated(result) = range.getDeclaringScope() } + Scope getDeclaringScope() { none() } /** Gets an access to this variable. */ VariableAccess getAnAccess() { result.getVariable() = this } @@ -30,12 +26,10 @@ class Variable extends TVariable { /** A local variable. */ class LocalVariable extends Variable, TLocalVariable { - override LocalVariable::Range range; - - final override LocalVariableAccess getAnAccess() { result.getVariable() = this } + override LocalVariableAccess getAnAccess() { none() } /** Gets the access where this local variable is first introduced. */ - VariableAccess getDefiningAccess() { result = range.getDefiningAccess() } + VariableAccess getDefiningAccess() { none() } /** * Holds if this variable is captured. For example in @@ -55,14 +49,14 @@ class LocalVariable extends Variable, TLocalVariable { } /** A global variable. */ -class GlobalVariable extends Variable, TGlobalVariable { +class GlobalVariable extends VariableReal, TGlobalVariable { override GlobalVariable::Range range; final override GlobalVariableAccess getAnAccess() { result.getVariable() = this } } /** An instance variable. */ -class InstanceVariable extends Variable, TInstanceVariable { +class InstanceVariable extends VariableReal, TInstanceVariable { override InstanceVariable::Range range; /** Holds is this variable is a class instance variable. */ @@ -72,7 +66,7 @@ class InstanceVariable extends Variable, TInstanceVariable { } /** A class variable. */ -class ClassVariable extends Variable, TClassVariable { +class ClassVariable extends VariableReal, TClassVariable { override ClassVariable::Range range; final override ClassVariableAccess getAnAccess() { result.getVariable() = this } @@ -95,6 +89,8 @@ class VariableAccess extends Expr, TVariableAccess { */ predicate isExplicitWrite(AstNode assignment) { explicitWriteAccess(toGenerated(this), toGenerated(assignment)) + or + this = assignment.(AssignExpr).getLeftOperand() } /** @@ -125,22 +121,12 @@ class VariableWriteAccess extends VariableAccess { /** An access to a variable where the value is read. */ class VariableReadAccess extends VariableAccess { - VariableReadAccess() { - not this instanceof VariableWriteAccess - or - // `x` in `x += y` is considered both a read and a write - this = any(AssignOperation a).getLeftOperand() - } + VariableReadAccess() { not this instanceof VariableWriteAccess } } /** An access to a local variable. */ class LocalVariableAccess extends VariableAccess, TLocalVariableAccess { - private Generated::Identifier g; - private LocalVariable v; - - LocalVariableAccess() { this = TLocalVariableAccess(g, v) } - - final override LocalVariable getVariable() { result = v } + override LocalVariable getVariable() { none() } final override string getAPrimaryQlClass() { result = "LocalVariableAccess" } @@ -160,8 +146,6 @@ class LocalVariableAccess extends VariableAccess, TLocalVariableAccess { * the access to `x` in the second `puts x` is not. */ final predicate isCapturedAccess() { isCapturedAccess(this) } - - final override string toString() { result = g.getValue() } } /** An access to a local variable where the value is updated. */ @@ -172,16 +156,9 @@ class LocalVariableReadAccess extends LocalVariableAccess, VariableReadAccess { /** An access to a global variable. */ class GlobalVariableAccess extends VariableAccess, TGlobalVariableAccess { - private Generated::GlobalVariable g; - private GlobalVariable v; - - GlobalVariableAccess() { this = TGlobalVariableAccess(g, v) } - - final override GlobalVariable getVariable() { result = v } + override GlobalVariable getVariable() { none() } final override string getAPrimaryQlClass() { result = "GlobalVariableAccess" } - - final override string toString() { result = g.getValue() } } /** An access to a global variable where the value is updated. */ @@ -192,28 +169,14 @@ class GlobalVariableReadAccess extends GlobalVariableAccess, VariableReadAccess /** An access to an instance variable. */ class InstanceVariableAccess extends VariableAccess, TInstanceVariableAccess { - private Generated::InstanceVariable g; - private InstanceVariable v; - - InstanceVariableAccess() { this = TInstanceVariableAccess(g, v) } - - final override InstanceVariable getVariable() { result = v } + override InstanceVariable getVariable() { none() } final override string getAPrimaryQlClass() { result = "InstanceVariableAccess" } - - final override string toString() { result = g.getValue() } } /** An access to a class variable. */ class ClassVariableAccess extends VariableAccess, TClassVariableAccess { - private Generated::ClassVariable g; - private ClassVariable v; - - ClassVariableAccess() { this = TClassVariableAccess(g, v) } - - final override ClassVariable getVariable() { result = v } + override ClassVariable getVariable() { none() } final override string getAPrimaryQlClass() { result = "ClassVariableAccess" } - - final override string toString() { result = g.getValue() } } diff --git a/ql/src/codeql_ruby/ast/internal/AST.qll b/ql/src/codeql_ruby/ast/internal/AST.qll index a7ad94ec652..9dd3c35058e 100644 --- a/ql/src/codeql_ruby/ast/internal/AST.qll +++ b/ql/src/codeql_ruby/ast/internal/AST.qll @@ -3,6 +3,7 @@ private import TreeSitter private import codeql_ruby.ast.internal.Parameter private import codeql_ruby.ast.internal.Variable private import codeql_ruby.AST as AST +private import Synthesis module MethodName { predicate range(Generated::UnderscoreMethodName g) { @@ -16,11 +17,16 @@ module MethodName { @token_identifier or @token_instance_variable or @token_operator; } +private predicate mkSynthChild(SynthKind kind, AST::AstNode parent, int i) { + any(Synthesis s).child(parent, i, SynthChild(kind)) +} + cached private module Cached { cached newtype TAstNode = - TAddExpr(Generated::Binary g) { g instanceof @binary_plus } or + TAddExprReal(Generated::Binary g) { g instanceof @binary_plus } or + TAddExprSynth(AST::AstNode parent, int i) { mkSynthChild(AddExprKind(), parent, i) } or TAliasStmt(Generated::Alias g) or TArgumentList(Generated::AstNode g) { ( @@ -50,7 +56,8 @@ private module Cached { TAssignExponentExpr(Generated::OperatorAssignment g) { g instanceof @operator_assignment_starstarequal } or - TAssignExpr(Generated::Assignment g) or + TAssignExprReal(Generated::Assignment g) or + TAssignExprSynth(AST::AstNode parent, int i) { mkSynthChild(AssignExprKind(), parent, i) } or TAssignLShiftExpr(Generated::OperatorAssignment g) { g instanceof @operator_assignment_langlelangleequal } or @@ -72,9 +79,16 @@ private module Cached { TBareSymbolLiteral(Generated::BareSymbol g) or TBeginBlock(Generated::BeginBlock g) or TBeginExpr(Generated::Begin g) or - TBitwiseAndExpr(Generated::Binary g) { g instanceof @binary_ampersand } or - TBitwiseOrExpr(Generated::Binary g) { g instanceof @binary_pipe } or - TBitwiseXorExpr(Generated::Binary g) { g instanceof @binary_caret } or + TBitwiseAndExprReal(Generated::Binary g) { g instanceof @binary_ampersand } or + TBitwiseAndExprSynth(AST::AstNode parent, int i) { + mkSynthChild(BitwiseAndExprKind(), parent, i) + } or + TBitwiseOrExprReal(Generated::Binary g) { g instanceof @binary_pipe } or + TBitwiseOrExprSynth(AST::AstNode parent, int i) { mkSynthChild(BitwiseOrExprKind(), parent, i) } or + TBitwiseXorExprReal(Generated::Binary g) { g instanceof @binary_caret } or + TBitwiseXorExprSynth(AST::AstNode parent, int i) { + mkSynthChild(BitwiseXorExprKind(), parent, i) + } or TBlockArgument(Generated::BlockArgument g) or TBlockParameter(Generated::BlockParameter g) or TBraceBlock(Generated::Block g) { not g.getParent() instanceof Generated::Lambda } or @@ -83,9 +97,12 @@ private module Cached { TCaseExpr(Generated::Case g) or TCharacterLiteral(Generated::Character g) or TClassDeclaration(Generated::Class g) or - TClassVariableAccess(Generated::ClassVariable g, AST::ClassVariable v) { + TClassVariableAccessReal(Generated::ClassVariable g, AST::ClassVariable v) { ClassVariableAccess::range(g, v) } or + TClassVariableAccessSynth(AST::AstNode parent, int i, AST::ClassVariable v) { + mkSynthChild(ClassVariableAccessKind(v), parent, i) + } or TComplementExpr(Generated::Unary g) { g instanceof @unary_tilde } or TComplexLiteral(Generated::Complex g) or TDefinedExpr(Generated::Unary g) { g instanceof @unary_definedquestion } or @@ -93,7 +110,8 @@ private module Cached { TDestructuredLeftAssignment(Generated::DestructuredLeftAssignment g) { not strictcount(int i | exists(g.getParent().(Generated::LeftAssignmentList).getChild(i))) = 1 } or - TDivExpr(Generated::Binary g) { g instanceof @binary_slash } or + TDivExprReal(Generated::Binary g) { g instanceof @binary_slash } or + TDivExprSynth(AST::AstNode parent, int i) { mkSynthChild(DivExprKind(), parent, i) } or TDo(Generated::Do g) or TDoBlock(Generated::DoBlock g) { not g.getParent() instanceof Generated::Lambda } or TElementReference(Generated::ElementReference g) or @@ -103,17 +121,20 @@ private module Cached { TEndBlock(Generated::EndBlock g) or TEnsure(Generated::Ensure g) or TEqExpr(Generated::Binary g) { g instanceof @binary_equalequal } or - TExplicitSelf(Generated::Self g) or - TExponentExpr(Generated::Binary g) { g instanceof @binary_starstar } or + TExponentExprReal(Generated::Binary g) { g instanceof @binary_starstar } or + TExponentExprSynth(AST::AstNode parent, int i) { mkSynthChild(ExponentExprKind(), parent, i) } or TFalseLiteral(Generated::False g) or TFloatLiteral(Generated::Float g) { not any(Generated::Rational r).getChild() = g } or TForExpr(Generated::For g) or TForIn(Generated::In g) or // TODO REMOVE TGEExpr(Generated::Binary g) { g instanceof @binary_rangleequal } or TGTExpr(Generated::Binary g) { g instanceof @binary_rangle } or - TGlobalVariableAccess(Generated::GlobalVariable g, AST::GlobalVariable v) { + TGlobalVariableAccessReal(Generated::GlobalVariable g, AST::GlobalVariable v) { GlobalVariableAccess::range(g, v) } or + TGlobalVariableAccessSynth(AST::AstNode parent, int i, AST::GlobalVariable v) { + mkSynthChild(GlobalVariableAccessKind(v), parent, i) + } or THashKeySymbolLiteral(Generated::HashKeySymbol g) or THashLiteral(Generated::Hash g) or THashSplatArgument(Generated::HashSplatArgument g) or @@ -122,34 +143,44 @@ private module Cached { TIdentifierMethodCall(Generated::Identifier g) { isIdentifierMethodCall(g) } or TIf(Generated::If g) or TIfModifierExpr(Generated::IfModifier g) or - TImplicitSelf(Generated::AstNode g) { - isIdentifierMethodCall(g) - or - isRegularMethodCall(g) and - not exists(g.(Generated::Call).getReceiver()) and - not exists(g.(Generated::Call).getMethod().(Generated::ScopeResolution).getScope()) - } or - TInstanceVariableAccess(Generated::InstanceVariable g, AST::InstanceVariable v) { + TInstanceVariableAccessReal(Generated::InstanceVariable g, AST::InstanceVariable v) { InstanceVariableAccess::range(g, v) } or + TInstanceVariableAccessSynth(AST::AstNode parent, int i, AST::InstanceVariable v) { + mkSynthChild(InstanceVariableAccessKind(v), parent, i) + } or TIntegerLiteral(Generated::Integer g) { not any(Generated::Rational r).getChild() = g } or TKeywordParameter(Generated::KeywordParameter g) or TLEExpr(Generated::Binary g) { g instanceof @binary_langleequal } or - TLShiftExpr(Generated::Binary g) { g instanceof @binary_langlelangle } or + TLShiftExprReal(Generated::Binary g) { g instanceof @binary_langlelangle } or + TLShiftExprSynth(AST::AstNode parent, int i) { mkSynthChild(LShiftExprKind(), parent, i) } or TLTExpr(Generated::Binary g) { g instanceof @binary_langle } or TLambda(Generated::Lambda g) or TLeftAssignmentList(Generated::LeftAssignmentList g) or - TLocalVariableAccess(Generated::Identifier g, AST::LocalVariable v) { + TLocalVariableAccessReal(Generated::Identifier g, AST::LocalVariable v) { LocalVariableAccess::range(g, v) } or - TLogicalAndExpr(Generated::Binary g) { + TLocalVariableAccessSynth(AST::AstNode parent, int i, AST::LocalVariable v) { + mkSynthChild(LocalVariableAccessRealKind(v), parent, i) + or + mkSynthChild(LocalVariableAccessSynthKind(v), parent, i) + } or + TLogicalAndExprReal(Generated::Binary g) { g instanceof @binary_and or g instanceof @binary_ampersandampersand } or - TLogicalOrExpr(Generated::Binary g) { g instanceof @binary_or or g instanceof @binary_pipepipe } or + TLogicalAndExprSynth(AST::AstNode parent, int i) { + mkSynthChild(LogicalAndExprKind(), parent, i) + } or + TLogicalOrExprReal(Generated::Binary g) { + g instanceof @binary_or or g instanceof @binary_pipepipe + } or + TLogicalOrExprSynth(AST::AstNode parent, int i) { mkSynthChild(LogicalOrExprKind(), parent, i) } or TMethod(Generated::Method g) or TModuleDeclaration(Generated::Module g) or - TModuloExpr(Generated::Binary g) { g instanceof @binary_percent } or - TMulExpr(Generated::Binary g) { g instanceof @binary_star } or + TModuloExprReal(Generated::Binary g) { g instanceof @binary_percent } or + TModuloExprSynth(AST::AstNode parent, int i) { mkSynthChild(ModuloExprKind(), parent, i) } or + TMulExprReal(Generated::Binary g) { g instanceof @binary_star } or + TMulExprSynth(AST::AstNode parent, int i) { mkSynthChild(MulExprKind(), parent, i) } or TNEExpr(Generated::Binary g) { g instanceof @binary_bangequal } or TNextStmt(Generated::Next g) or TNilLiteral(Generated::Nil g) or @@ -157,8 +188,12 @@ private module Cached { TNotExpr(Generated::Unary g) { g instanceof @unary_bang or g instanceof @unary_not } or TOptionalParameter(Generated::OptionalParameter g) or TPair(Generated::Pair g) or - TParenthesizedExpr(Generated::ParenthesizedStatements g) or - TRShiftExpr(Generated::Binary g) { g instanceof @binary_ranglerangle } or + TParenthesizedExprReal(Generated::ParenthesizedStatements g) or + TParenthesizedExprSynth(AST::AstNode parent, int i) { + mkSynthChild(ParenthesizedExprKind(), parent, i) + } or + TRShiftExprReal(Generated::Binary g) { g instanceof @binary_ranglerangle } or + TRShiftExprSynth(AST::AstNode parent, int i) { mkSynthChild(RShiftExprKind(), parent, i) } or TRangeLiteral(Generated::Range g) or TRationalLiteral(Generated::Rational g) or TRedoStmt(Generated::Redo g) or @@ -187,6 +222,8 @@ private module Cached { i = g.getName() and not exists(Generated::Call c | c.getMethod() = g) } or + TSelfReal(Generated::Self g) or + TSelfSynth(AST::AstNode parent, int i) { mkSynthChild(SelfKind(), parent, i) } or TSimpleParameter(Generated::Identifier g) { g instanceof Parameter::Range } or TSimpleSymbolLiteral(Generated::SimpleSymbol g) or TSingletonClass(Generated::SingletonClass g) or @@ -201,7 +238,8 @@ private module Cached { TStringTextComponent(Generated::Token g) { g instanceof Generated::StringContent or g instanceof Generated::HeredocContent } or - TSubExpr(Generated::Binary g) { g instanceof @binary_minus } or + TSubExprReal(Generated::Binary g) { g instanceof @binary_minus } or + TSubExprSynth(AST::AstNode parent, int i) { mkSynthChild(SubExprKind(), parent, i) } or TSubshellLiteral(Generated::Subshell g) or TSymbolArrayLiteral(Generated::SymbolArray g) or TTernaryIfExpr(Generated::Conditional g) or @@ -245,7 +283,7 @@ private module Cached { */ cached Generated::AstNode toGenerated(AST::AstNode n) { - n = TAddExpr(result) or + n = TAddExprReal(result) or n = TAliasStmt(result) or n = TArgumentList(result) or n = TAssignAddExpr(result) or @@ -254,7 +292,7 @@ private module Cached { n = TAssignBitwiseXorExpr(result) or n = TAssignDivExpr(result) or n = TAssignExponentExpr(result) or - n = TAssignExpr(result) or + n = TAssignExprReal(result) or n = TAssignLShiftExpr(result) or n = TAssignLogicalAndExpr(result) or n = TAssignLogicalOrExpr(result) or @@ -266,9 +304,9 @@ private module Cached { n = TBareSymbolLiteral(result) or n = TBeginBlock(result) or n = TBeginExpr(result) or - n = TBitwiseAndExpr(result) or - n = TBitwiseOrExpr(result) or - n = TBitwiseXorExpr(result) or + n = TBitwiseAndExprReal(result) or + n = TBitwiseOrExprReal(result) or + n = TBitwiseXorExprReal(result) or n = TBlockArgument(result) or n = TBlockParameter(result) or n = TBraceBlock(result) or @@ -277,13 +315,13 @@ private module Cached { n = TCaseExpr(result) or n = TCharacterLiteral(result) or n = TClassDeclaration(result) or - n = TClassVariableAccess(result, _) or + n = TClassVariableAccessReal(result, _) or n = TComplementExpr(result) or n = TComplexLiteral(result) or n = TDefinedExpr(result) or n = TDelimitedSymbolLiteral(result) or n = TDestructuredLeftAssignment(result) or - n = TDivExpr(result) or + n = TDivExprReal(result) or n = TDo(result) or n = TDoBlock(result) or n = TElementReference(result) or @@ -293,15 +331,14 @@ private module Cached { n = TEndBlock(result) or n = TEnsure(result) or n = TEqExpr(result) or - n = TExplicitSelf(result) or - n = TExponentExpr(result) or + n = TExponentExprReal(result) or n = TFalseLiteral(result) or n = TFloatLiteral(result) or n = TForExpr(result) or n = TForIn(result) or // TODO REMOVE n = TGEExpr(result) or n = TGTExpr(result) or - n = TGlobalVariableAccess(result, _) or + n = TGlobalVariableAccessReal(result, _) or n = THashKeySymbolLiteral(result) or n = THashLiteral(result) or n = THashSplatArgument(result) or @@ -310,21 +347,21 @@ private module Cached { n = TIdentifierMethodCall(result) or n = TIf(result) or n = TIfModifierExpr(result) or - n = TInstanceVariableAccess(result, _) or + n = TInstanceVariableAccessReal(result, _) or n = TIntegerLiteral(result) or n = TKeywordParameter(result) or n = TLEExpr(result) or - n = TLShiftExpr(result) or + n = TLShiftExprReal(result) or n = TLTExpr(result) or n = TLambda(result) or n = TLeftAssignmentList(result) or - n = TLocalVariableAccess(result, _) or - n = TLogicalAndExpr(result) or - n = TLogicalOrExpr(result) or + n = TLocalVariableAccessReal(result, _) or + n = TLogicalAndExprReal(result) or + n = TLogicalOrExprReal(result) or n = TMethod(result) or n = TModuleDeclaration(result) or - n = TModuloExpr(result) or - n = TMulExpr(result) or + n = TModuloExprReal(result) or + n = TMulExprReal(result) or n = TNEExpr(result) or n = TNextStmt(result) or n = TNilLiteral(result) or @@ -332,8 +369,8 @@ private module Cached { n = TNotExpr(result) or n = TOptionalParameter(result) or n = TPair(result) or - n = TParenthesizedExpr(result) or - n = TRShiftExpr(result) or + n = TParenthesizedExprReal(result) or + n = TRShiftExprReal(result) or n = TRangeLiteral(result) or n = TRationalLiteral(result) or n = TRedoStmt(result) or @@ -349,6 +386,7 @@ private module Cached { n = TReturnStmt(result) or n = TScopeResolutionConstantAccess(result, _) or n = TScopeResolutionMethodCall(result, _) or + n = TSelfReal(result) or n = TSimpleParameter(result) or n = TSimpleSymbolLiteral(result) or n = TSingletonClass(result) or @@ -361,7 +399,7 @@ private module Cached { n = TStringEscapeSequenceComponent(result) or n = TStringInterpolationComponent(result) or n = TStringTextComponent(result) or - n = TSubExpr(result) or + n = TSubExprReal(result) or n = TSubshellLiteral(result) or n = TSymbolArrayLiteral(result) or n = TTernaryIfExpr(result) or @@ -385,14 +423,105 @@ private module Cached { n = TYieldCall(result) } + /** Gets the `i`th synthesized child of `parent`. */ + cached + AST::AstNode getSynthChild(AST::AstNode parent, int i) { + exists(SynthKind kind | mkSynthChild(kind, parent, i) | + kind = AddExprKind() and + result = TAddExprSynth(parent, i) + or + kind = AssignExprKind() and + result = TAssignExprSynth(parent, i) + or + kind = BitwiseAndExprKind() and + result = TBitwiseAndExprSynth(parent, i) + or + kind = BitwiseOrExprKind() and + result = TBitwiseOrExprSynth(parent, i) + or + kind = BitwiseXorExprKind() and + result = TBitwiseXorExprSynth(parent, i) + or + exists(AST::ClassVariable v | + kind = ClassVariableAccessKind(v) and + result = TClassVariableAccessSynth(parent, i, v) + ) + or + kind = DivExprKind() and + result = TDivExprSynth(parent, i) + or + kind = ExponentExprKind() and + result = TExponentExprSynth(parent, i) + or + exists(AST::GlobalVariable v | + kind = GlobalVariableAccessKind(v) and + result = TGlobalVariableAccessSynth(parent, i, v) + ) + or + exists(AST::InstanceVariable v | + kind = InstanceVariableAccessKind(v) and + result = TInstanceVariableAccessSynth(parent, i, v) + ) + or + kind = LShiftExprKind() and + result = TLShiftExprSynth(parent, i) + or + exists(AST::LocalVariable v | result = TLocalVariableAccessSynth(parent, i, v) | + kind = LocalVariableAccessRealKind(v) + or + kind = LocalVariableAccessSynthKind(v) + ) + or + kind = LogicalAndExprKind() and + result = TLogicalAndExprSynth(parent, i) + or + kind = LogicalOrExprKind() and + result = TLogicalOrExprSynth(parent, i) + or + kind = ModuloExprKind() and + result = TModuloExprSynth(parent, i) + or + kind = MulExprKind() and + result = TMulExprSynth(parent, i) + or + kind = ParenthesizedExprKind() and + result = TParenthesizedExprSynth(parent, i) + or + kind = RShiftExprKind() and + result = TRShiftExprSynth(parent, i) + or + kind = SelfKind() and + result = TSelfSynth(parent, i) + or + kind = SubExprKind() and + result = TSubExprSynth(parent, i) + ) + } + + /** + * Holds if the `i`th child of `parent` is `child`. Either `parent` or + * `child` (or both) is a synthesized node. + */ + cached + predicate synthChild(AST::AstNode parent, int i, AST::AstNode child) { + child = getSynthChild(parent, i) + or + any(Synthesis s).child(parent, i, RealChild(child)) + } + /** * Like `toGenerated`, but also returns generated nodes for synthesized AST * nodes. */ cached Generated::AstNode toGeneratedInclSynth(AST::AstNode n) { - result = toGenerated(n) or - n = TImplicitSelf(result) + result = toGenerated(n) + or + not exists(toGenerated(n)) and + exists(AST::AstNode parent | + synthChild(parent, _, n) and + result = toGeneratedInclSynth(parent) + ) } } @@ -421,7 +550,7 @@ class TConditionalLoop = TWhileExpr or TUntilExpr or TWhileModifierExpr or TUnti class TLoop = TConditionalLoop or TForExpr; -class TSelf = TExplicitSelf or TImplicitSelf; +class TSelf = TSelfReal or TSelfSynth; class TExpr = TSelf or TArgumentList or TRescueClause or TRescueModifierExpr or TPair or TStringConcatenation or @@ -433,6 +562,8 @@ class TStmtSequence = TBeginBlock or TEndBlock or TThen or TElse or TDo or TEnsure or TStringInterpolationComponent or TBlock or TBodyStmt or TParenthesizedExpr; +class TParenthesizedExpr = TParenthesizedExprReal or TParenthesizedExprSynth; + class TBodyStmt = TBeginExpr or TModuleBase or TMethod or TLambda or TDoBlock or TSingletonMethod; class TLiteral = @@ -485,17 +616,45 @@ class TBinaryOperation = class TBinaryArithmeticOperation = TAddExpr or TSubExpr or TMulExpr or TDivExpr or TModuloExpr or TExponentExpr; +class TAddExpr = TAddExprReal or TAddExprSynth; + +class TSubExpr = TSubExprReal or TSubExprSynth; + +class TMulExpr = TMulExprReal or TMulExprSynth; + +class TDivExpr = TDivExprReal or TDivExprSynth; + +class TModuloExpr = TModuloExprReal or TModuloExprSynth; + +class TExponentExpr = TExponentExprReal or TExponentExprSynth; + class TBinaryLogicalOperation = TLogicalAndExpr or TLogicalOrExpr; +class TLogicalAndExpr = TLogicalAndExprReal or TLogicalAndExprSynth; + +class TLogicalOrExpr = TLogicalOrExprReal or TLogicalOrExprSynth; + class TBinaryBitwiseOperation = TLShiftExpr or TRShiftExpr or TBitwiseAndExpr or TBitwiseOrExpr or TBitwiseXorExpr; +class TLShiftExpr = TLShiftExprReal or TLShiftExprSynth; + +class TRShiftExpr = TRShiftExprReal or TRShiftExprSynth; + +class TBitwiseAndExpr = TBitwiseAndExprReal or TBitwiseAndExprSynth; + +class TBitwiseOrExpr = TBitwiseOrExprReal or TBitwiseOrExprSynth; + +class TBitwiseXorExpr = TBitwiseXorExprReal or TBitwiseXorExprSynth; + class TComparisonOperation = TEqualityOperation or TRelationalOperation; class TEqualityOperation = TEqExpr or TNEExpr or TCaseEqExpr; class TRelationalOperation = TGTExpr or TGEExpr or TLTExpr or TLEExpr; +class TAssignExpr = TAssignExprReal or TAssignExprSynth; + class TAssignment = TAssignExpr or TAssignOperation; class TAssignOperation = @@ -531,3 +690,11 @@ class TTuplePattern = TTuplePatternParameter or TDestructuredLeftAssignment or T class TVariableAccess = TLocalVariableAccess or TGlobalVariableAccess or TInstanceVariableAccess or TClassVariableAccess; + +class TLocalVariableAccess = TLocalVariableAccessReal or TLocalVariableAccessSynth; + +class TGlobalVariableAccess = TGlobalVariableAccessReal or TGlobalVariableAccessSynth; + +class TInstanceVariableAccess = TInstanceVariableAccessReal or TInstanceVariableAccessSynth; + +class TClassVariableAccess = TClassVariableAccessReal or TClassVariableAccessSynth; diff --git a/ql/src/codeql_ruby/ast/internal/Module.qll b/ql/src/codeql_ruby/ast/internal/Module.qll index d7708271e11..1a0b56f961d 100644 --- a/ql/src/codeql_ruby/ast/internal/Module.qll +++ b/ql/src/codeql_ruby/ast/internal/Module.qll @@ -67,7 +67,7 @@ private module Cached { m = resolveScopeExpr(c.getReceiver()) or m = enclosingModule(c).getModule() and - c.receiverIsSelf() + c.getReceiver() instanceof Self ) and result = resolveScopeExpr(c.getAnArgument()) ) @@ -81,7 +81,7 @@ private module Cached { m = resolveScopeExpr(c.getReceiver()) or m = enclosingModule(c).getModule() and - c.receiverIsSelf() + c.getReceiver() instanceof Self ) and result = resolveScopeExpr(c.getAnArgument()) ) diff --git a/ql/src/codeql_ruby/ast/internal/Synthesis.qll b/ql/src/codeql_ruby/ast/internal/Synthesis.qll new file mode 100644 index 00000000000..6cdca0db8e8 --- /dev/null +++ b/ql/src/codeql_ruby/ast/internal/Synthesis.qll @@ -0,0 +1,173 @@ +/** Provides predicates for synthesizing AST nodes. */ + +private import AST +private import TreeSitter +private import codeql_ruby.ast.internal.Parameter +private import codeql_ruby.ast.internal.Variable +private import codeql_ruby.AST + +/** A synthesized AST node kind. */ +newtype SynthKind = + AddExprKind() or + AssignExprKind() or + BitwiseAndExprKind() or + BitwiseOrExprKind() or + BitwiseXorExprKind() or + ClassVariableAccessKind(ClassVariable v) or + DivExprKind() or + ExponentExprKind() or + GlobalVariableAccessKind(GlobalVariable v) or + InstanceVariableAccessKind(InstanceVariable v) or + LShiftExprKind() or + LocalVariableAccessRealKind(LocalVariableReal v) or + LocalVariableAccessSynthKind(TLocalVariableSynth v) or + LogicalAndExprKind() or + LogicalOrExprKind() or + ModuloExprKind() or + MulExprKind() or + ParenthesizedExprKind() or + RShiftExprKind() or + SelfKind() or + SubExprKind() + +/** + * An AST child. + * + * Either a new synthesized node or a reference to an existing node. + */ +newtype Child = + SynthChild(SynthKind k) or + RealChild(AstNode n) + +private newtype TSynthesis = MkSynthesis() + +/** A class used for synthesizing AST nodes. */ +class Synthesis extends TSynthesis { + /** + * Holds if a node should be synthesized as the `i`th child of `parent`, or if + * a non-synthesized node should be the `i`th child of synthesized node `parent`. + * + * `i = -1` is used to represent that the synthesized node is a desugared version + * of its parent. + */ + predicate child(AstNode parent, int i, Child child) { none() } + + /** + * Holds if a local variable, identified by `i`, should be synthesized for AST + * node `n`. + */ + predicate localVariable(AstNode n, int i) { none() } + + /** + * Holds if `n` should be excluded from `ControlFlowTree` in the CFG construction. + */ + predicate excludeFromControlFlowTree(AstNode n) { none() } + + final string toString() { none() } +} + +private module ImplicitSelfSynthesis { + private class IdentifierMethodCallSelfSynthesis extends Synthesis { + final override predicate child(AstNode parent, int i, Child child) { + child = SynthChild(SelfKind()) and + parent = TIdentifierMethodCall(_) and + i = 0 + } + } + + private class RegularMethodCallSelfSynthesis extends Synthesis { + final override predicate child(AstNode parent, int i, Child child) { + child = SynthChild(SelfKind()) and + i = 0 and + exists(Generated::AstNode g | + parent = TRegularMethodCall(g) and + // If there's no explicit receiver (or scope resolution that acts like a + // receiver), then the receiver is implicitly `self`. N.B. `::Foo()` is + // not valid Ruby. + not exists(g.(Generated::Call).getReceiver()) and + not exists(g.(Generated::Call).getMethod().(Generated::ScopeResolution).getScope()) + ) + } + } +} + +private module AssignOperationDesugar { + /** + * Gets the operator kind to synthesize for operator assignment `ao`. + */ + private SynthKind getKind(AssignOperation ao) { + ao instanceof AssignAddExpr and result = AddExprKind() + or + ao instanceof AssignSubExpr and result = SubExprKind() + or + ao instanceof AssignMulExpr and result = MulExprKind() + or + ao instanceof AssignDivExpr and result = DivExprKind() + or + ao instanceof AssignModuloExpr and result = ModuloExprKind() + or + ao instanceof AssignExponentExpr and result = ExponentExprKind() + or + ao instanceof AssignLogicalAndExpr and result = LogicalAndExprKind() + or + ao instanceof AssignLogicalOrExpr and result = LogicalOrExprKind() + or + ao instanceof AssignLShiftExpr and result = LShiftExprKind() + or + ao instanceof AssignRShiftExpr and result = RShiftExprKind() + or + ao instanceof AssignBitwiseAndExpr and result = BitwiseAndExprKind() + or + ao instanceof AssignBitwiseOrExpr and result = BitwiseOrExprKind() + or + ao instanceof AssignBitwiseXorExpr and result = BitwiseXorExprKind() + } + + /** + * ```rb + * x += y + * ``` + * + * desguars to + * + * ```rb + * x = x + y + * ``` + * + * when `x` is a variable. + */ + private class VariableAssignOperationSynthesis extends Synthesis { + final override predicate child(AstNode parent, int i, Child child) { + exists(AssignOperation ao, VariableReal v | + v = ao.getLeftOperand().(VariableAccessReal).getVariableReal() + | + parent = ao and + i = -1 and + child = SynthChild(AssignExprKind()) + or + exists(AstNode assign | assign = getSynthChild(ao, -1) | + parent = assign and + i = 0 and + child = RealChild(ao.getLeftOperand()) + or + parent = assign and + i = 1 and + child = SynthChild(getKind(ao)) + or + parent = getSynthChild(assign, 1) and + ( + i = 0 and + child = + SynthChild([ + LocalVariableAccessRealKind(v).(SynthKind), InstanceVariableAccessKind(v), + ClassVariableAccessKind(v), GlobalVariableAccessKind(v) + ]) + or + i = 1 and + child = RealChild(ao.getRightOperand()) + ) + ) + ) + } + } +} diff --git a/ql/src/codeql_ruby/ast/internal/Variable.qll b/ql/src/codeql_ruby/ast/internal/Variable.qll index fcd1e428862..456286f20a2 100644 --- a/ql/src/codeql_ruby/ast/internal/Variable.qll +++ b/ql/src/codeql_ruby/ast/internal/Variable.qll @@ -4,6 +4,7 @@ private import codeql_ruby.AST private import codeql_ruby.ast.internal.AST private import codeql_ruby.ast.internal.Parameter private import codeql_ruby.ast.internal.Scope +private import codeql_ruby.ast.internal.Synthesis /** * Holds if `n` is in the left-hand-side of an explicit assignment `assignment`. @@ -128,7 +129,7 @@ private module Cached { other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn() ) } or - TLocalVariable(Scope::Range scope, string name, Generated::Identifier i) { + TLocalVariableReal(Scope::Range scope, string name, Generated::Identifier i) { scopeDefinesParameterVariable(scope, name, i) or i = @@ -139,7 +140,8 @@ private module Cached { ) and not scopeDefinesParameterVariable(scope, name, _) and not inherits(scope, name, _) - } + } or + TLocalVariableSynth(AstNode n, int i) { any(Synthesis s).localVariable(n, i) } // Db types that can be vcalls private class VcallToken = @@ -288,7 +290,7 @@ private module Cached { } cached - predicate access(Generated::Identifier access, Variable::Range variable) { + predicate access(Generated::Identifier access, VariableReal::Range variable) { exists(string name | variable.getName() = name and name = access.getValue() @@ -372,8 +374,10 @@ private predicate inherits(Scope::Range scope, string name, Scope::Range outer) ) } -module Variable { - class Range extends TVariable { +class TVariableReal = TGlobalVariable or TClassVariable or TInstanceVariable or TLocalVariableReal; + +module VariableReal { + class Range extends TVariableReal { abstract string getName(); string toString() { result = this.getName() } @@ -384,13 +388,15 @@ module Variable { } } +class TLocalVariable = TLocalVariableReal or TLocalVariableSynth; + module LocalVariable { - class Range extends Variable::Range, TLocalVariable { + class Range extends VariableReal::Range, TLocalVariableReal { private Scope::Range scope; private string name; private Generated::Identifier i; - Range() { this = TLocalVariable(scope, name, i) } + Range() { this = TLocalVariableReal(scope, name, i) } final override string getName() { result = name } @@ -402,8 +408,41 @@ module LocalVariable { } } +class VariableReal extends Variable, TVariableReal { + VariableReal::Range range; + + VariableReal() { range = this } + + final override string getName() { result = range.getName() } + + final override Location getLocation() { result = range.getLocation() } + + final override Scope getDeclaringScope() { toGenerated(result) = range.getDeclaringScope() } +} + +class LocalVariableReal extends VariableReal, LocalVariable, TLocalVariableReal { + override LocalVariable::Range range; + + final override LocalVariableAccessReal getAnAccess() { result.getVariable() = this } + + final override VariableAccess getDefiningAccess() { result = range.getDefiningAccess() } +} + +class LocalVariableSynth extends LocalVariable, TLocalVariableSynth { + private AstNode n; + private int i; + + LocalVariableSynth() { this = TLocalVariableSynth(n, i) } + + final override string getName() { result = "__synth__" + i } + + final override Location getLocation() { result = n.getLocation() } + + final override Scope getDeclaringScope() { none() } // not relevant for synthesized variables +} + module GlobalVariable { - class Range extends Variable::Range, TGlobalVariable { + class Range extends VariableReal::Range, TGlobalVariable { private string name; Range() { this = TGlobalVariable(name) } @@ -417,7 +456,7 @@ module GlobalVariable { } module InstanceVariable { - class Range extends Variable::Range, TInstanceVariable { + class Range extends VariableReal::Range, TInstanceVariable { private ModuleBase::Range scope; private boolean instance; private string name; @@ -436,7 +475,7 @@ module InstanceVariable { } module ClassVariable { - class Range extends Variable::Range, TClassVariable { + class Range extends VariableReal::Range, TClassVariable { private ModuleBase::Range scope; private string name; private Generated::AstNode decl; @@ -464,16 +503,121 @@ module LocalVariableAccess { } } +class TVariableAccessReal = + TLocalVariableAccessReal or TGlobalVariableAccess or TInstanceVariableAccess or + TClassVariableAccess; + +abstract class VariableAccessReal extends VariableAccess, TVariableAccessReal { + abstract VariableReal getVariableReal(); +} + +private class LocalVariableAccessReal extends VariableAccessReal, LocalVariableAccess, + TLocalVariableAccessReal { + private Generated::Identifier g; + private LocalVariable v; + + LocalVariableAccessReal() { this = TLocalVariableAccessReal(g, v) } + + final override LocalVariable getVariable() { result = v } + + final override LocalVariableReal getVariableReal() { result = v } + + final override string toString() { result = g.getValue() } +} + +private class LocalVariableAccessSynth extends LocalVariableAccess, TLocalVariableAccessSynth { + private LocalVariable v; + + LocalVariableAccessSynth() { this = TLocalVariableAccessSynth(_, _, v) } + + final override LocalVariable getVariable() { result = v } + + final override string toString() { result = v.getName() } +} + module GlobalVariableAccess { predicate range(Generated::GlobalVariable n, GlobalVariable v) { n.getValue() = v.getName() } } +private class GlobalVariableAccessReal extends VariableAccessReal, GlobalVariableAccess, + TGlobalVariableAccessReal { + private Generated::GlobalVariable g; + private GlobalVariable v; + + GlobalVariableAccessReal() { this = TGlobalVariableAccessReal(g, v) } + + final override GlobalVariable getVariable() { result = v } + + final override GlobalVariable getVariableReal() { result = v } + + final override string toString() { result = g.getValue() } +} + +private class GlobalVariableAccessSynth extends GlobalVariableAccess, TGlobalVariableAccessSynth { + private GlobalVariable v; + + GlobalVariableAccessSynth() { this = TGlobalVariableAccessSynth(_, _, v) } + + final override GlobalVariable getVariable() { result = v } + + final override string toString() { result = v.getName() } +} + module InstanceVariableAccess { predicate range(Generated::InstanceVariable n, InstanceVariable v) { instanceVariableAccess(n, v) } } +private class InstanceVariableAccessReal extends VariableAccessReal, InstanceVariableAccess, + TInstanceVariableAccessReal { + private Generated::InstanceVariable g; + private InstanceVariable v; + + InstanceVariableAccessReal() { this = TInstanceVariableAccessReal(g, v) } + + final override InstanceVariable getVariable() { result = v } + + final override InstanceVariable getVariableReal() { result = v } + + final override string toString() { result = g.getValue() } +} + +private class InstanceVariableAccessSynth extends InstanceVariableAccess, + TInstanceVariableAccessSynth { + private InstanceVariable v; + + InstanceVariableAccessSynth() { this = TInstanceVariableAccessSynth(_, _, v) } + + final override InstanceVariable getVariable() { result = v } + + final override string toString() { result = v.getName() } +} + module ClassVariableAccess { predicate range(Generated::ClassVariable n, ClassVariable v) { classVariableAccess(n, v) } } + +private class ClassVariableAccessReal extends VariableAccessReal, ClassVariableAccess, + TClassVariableAccessReal { + private Generated::ClassVariable g; + private ClassVariable v; + + ClassVariableAccessReal() { this = TClassVariableAccessReal(g, v) } + + final override ClassVariable getVariable() { result = v } + + final override ClassVariable getVariableReal() { result = v } + + final override string toString() { result = g.getValue() } +} + +private class ClassVariableAccessSynth extends ClassVariableAccess, TClassVariableAccessSynth { + private ClassVariable v; + + ClassVariableAccessSynth() { this = TClassVariableAccessSynth(_, _, v) } + + final override ClassVariable getVariable() { result = v } + + final override string toString() { result = v.getName() } +} diff --git a/ql/src/codeql_ruby/controlflow/CfgNodes.qll b/ql/src/codeql_ruby/controlflow/CfgNodes.qll index 2c6f9f7a809..89c0ea8b3fd 100644 --- a/ql/src/codeql_ruby/controlflow/CfgNodes.qll +++ b/ql/src/codeql_ruby/controlflow/CfgNodes.qll @@ -159,6 +159,13 @@ abstract private class ExprChildMapping extends Expr { ) } + private Expr desugar(Expr n) { + result = n.getDesugared() + or + not exists(n.getDesugared()) and + result = n + } + /** * Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn` * is a control-flow node for this expression, and `cfnChild` is a control-flow @@ -171,13 +178,13 @@ abstract private class ExprChildMapping extends Expr { exists(BasicBlock bb | this.reachesBasicBlockBase(child, cfn, bb) and cfnChild = bb.getANode() and - cfnChild = child.getAControlFlowNode() + cfnChild = desugar(child).getAControlFlowNode() ) or exists(BasicBlock bb | this.reachesBasicBlockRec(child, cfn, bb) and cfnChild = bb.getANode() and - cfnChild = child.getAControlFlowNode() + cfnChild = desugar(child).getAControlFlowNode() ) } } diff --git a/ql/src/codeql_ruby/controlflow/internal/Cfg.ql b/ql/src/codeql_ruby/controlflow/internal/Cfg.ql deleted file mode 100644 index a0b0200b346..00000000000 --- a/ql/src/codeql_ruby/controlflow/internal/Cfg.ql +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @kind graph - * @id rb/test/cfg - */ - -import codeql_ruby.CFG - -query predicate nodes(CfgNode n, string attr, string val) { - attr = "semmle.order" and - val = - any(int i | - n = - rank[i](CfgNode p | - | - p - order by - p.getLocation().getFile().getBaseName(), p.getLocation().getFile().getAbsolutePath(), - p.getLocation().getStartLine(), p.getLocation().getStartColumn() - ) - ).toString() -} - -query predicate edges(CfgNode pred, CfgNode succ, string attr, string val) { - exists(SuccessorType t | succ = pred.getASuccessor(t) | - attr = "semmle.label" and - if t instanceof SuccessorTypes::NormalSuccessor then val = "" else val = t.toString() - ) -} diff --git a/ql/src/codeql_ruby/controlflow/internal/Cfg.qll b/ql/src/codeql_ruby/controlflow/internal/Cfg.qll new file mode 100644 index 00000000000..ebc840a0e9f --- /dev/null +++ b/ql/src/codeql_ruby/controlflow/internal/Cfg.qll @@ -0,0 +1,32 @@ +/** + * Import this module into a `.ql` file of `@kind graph` to render a CFG. The + * graph is restricted to nodes from `RelevantCfgNode`. + */ + +private import codeql.Locations +import codeql_ruby.CFG + +abstract class RelevantCfgNode extends CfgNode { } + +query predicate nodes(RelevantCfgNode n, string attr, string val) { + attr = "semmle.order" and + val = + any(int i | + n = + rank[i](RelevantCfgNode p, Location l | + l = p.getLocation() + | + p + order by + l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(), + l.getStartColumn() + ) + ).toString() +} + +query predicate edges(RelevantCfgNode pred, RelevantCfgNode succ, string attr, string val) { + exists(SuccessorType t | succ = pred.getASuccessor(t) | + attr = "semmle.label" and + if t instanceof SuccessorTypes::NormalSuccessor then val = "" else val = t.toString() + ) +} diff --git a/ql/src/codeql_ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ql/src/codeql_ruby/controlflow/internal/ControlFlowGraphImpl.qll index bd5e91670fd..79d7d203c96 100644 --- a/ql/src/codeql_ruby/controlflow/internal/ControlFlowGraphImpl.qll +++ b/ql/src/codeql_ruby/controlflow/internal/ControlFlowGraphImpl.qll @@ -35,6 +35,7 @@ private import codeql_ruby.AST private import codeql_ruby.ast.internal.AST as ASTInternal private import codeql_ruby.ast.internal.Scope private import codeql_ruby.ast.Scope +private import codeql_ruby.ast.internal.Synthesis private import codeql_ruby.ast.internal.TreeSitter private import codeql_ruby.ast.internal.Variable private import codeql_ruby.controlflow.ControlFlowGraph @@ -85,6 +86,8 @@ module CfgScope { } abstract private class ControlFlowTree extends AstNode { + ControlFlowTree() { not any(Synthesis s).excludeFromControlFlowTree(this) } + /** * Holds if `first` is the first element executed within this AST node. */ @@ -284,6 +287,8 @@ module Trees { } private class AssignOperationTree extends StandardPostOrderTree, AssignOperation { + AssignOperationTree() { not this.getLeftOperand() instanceof VariableAccess } + final override ControlFlowTree getChildNode(int i) { result = this.getLeftOperand() and i = 0 or @@ -728,6 +733,22 @@ module Trees { } } + private class DesugaredTree extends ControlFlowTree { + ControlFlowTree desugared; + + DesugaredTree() { desugared = this.getDesugared() } + + final override predicate propagatesAbnormal(AstNode child) { + desugared.propagatesAbnormal(child) + } + + final override predicate first(AstNode first) { desugared.first(first) } + + final override predicate last(AstNode last, Completion c) { desugared.last(last, c) } + + final override predicate succ(AstNode pred, AstNode succ, Completion c) { none() } + } + private class DoBlockTree extends BodyStmtPostOrderTree, DoBlock { /** Gets the `i`th child in the body of this block. */ final override AstNode getBodyChild(int i, boolean rescuable) { diff --git a/ql/src/codeql_ruby/printAst.qll b/ql/src/codeql_ruby/printAst.qll index 2737e456251..f5e883e7996 100644 --- a/ql/src/codeql_ruby/printAst.qll +++ b/ql/src/codeql_ruby/printAst.qll @@ -8,6 +8,13 @@ import AST +/** Holds if `n` appears in the desugaring of some other node. */ +predicate isDesugared(AstNode n) { + n = any(AstNode sugar).getDesugared() + or + isDesugared(n.getParent()) +} + /** * The query can extend this class to control which nodes are printed. */ @@ -17,7 +24,19 @@ class PrintAstConfiguration extends string { /** * Holds if the given node should be printed. */ - predicate shouldPrintNode(AstNode n) { any() } + predicate shouldPrintNode(AstNode n) { + not isDesugared(n) + or + not n.isSynthesized() + or + n.isSynthesized() and + not n = any(AstNode sugar).getDesugared() and + exists(AstNode parent | + parent = n.getParent() and + not parent.isSynthesized() and + not n = parent.getDesugared() + ) + } } /** @@ -32,12 +51,11 @@ class PrintAstNode extends AstNode { result = any(int i | this = - rank[i](AstNode p | - | - p - order by - p.getLocation().getFile().getBaseName(), p.getLocation().getFile().getAbsolutePath(), - p.getLocation().getStartLine(), p.getLocation().getStartColumn() + rank[i](AstNode p, Location l, File f | + l = p.getLocation() and + f = l.getFile() + | + p order by f.getBaseName(), f.getAbsolutePath(), l.getStartLine(), l.getStartColumn() ) ).toString() } @@ -75,10 +93,10 @@ query predicate nodes(PrintAstNode node, string key, string value) { query predicate edges(PrintAstNode source, PrintAstNode target, string key, string value) { source.shouldPrint() and target.shouldPrint() and - target = source.getAChild() and + target = source.getChild(_) and ( key = "semmle.label" and - value = concat(string name | source.getChild(name) = target | name, "/") + value = strictconcat(string name | source.getChild(name) = target | name, "/") or key = "semmle.order" and value = target.getProperty("semmle.order") diff --git a/ql/test/library-tests/ast/Ast.ql b/ql/test/library-tests/ast/Ast.ql index 4cd412f83a0..babafaac548 100644 --- a/ql/test/library-tests/ast/Ast.ql +++ b/ql/test/library-tests/ast/Ast.ql @@ -1,6 +1,5 @@ /** * @kind graph - * @id rb/test/print-ast */ import codeql_ruby.printAst diff --git a/ql/test/library-tests/ast/AstDesugar.expected b/ql/test/library-tests/ast/AstDesugar.expected new file mode 100644 index 00000000000..6d3ce654d19 --- /dev/null +++ b/ql/test/library-tests/ast/AstDesugar.expected @@ -0,0 +1,180 @@ +calls/calls.rb: +# 66| [AssignExpr] ... = ... +# 66| getAnOperand/getLeftOperand: [LocalVariableAccess] var1 +# 66| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 66| getAnOperand/getLeftOperand: [LocalVariableAccess] var1 +# 66| getAnOperand/getRightOperand: [MethodCall] call to bar +# 66| getReceiver: [Self] self +# 67| [AssignExpr] ... = ... +# 67| getAnOperand/getLeftOperand: [LocalVariableAccess] var1 +# 67| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 67| getAnOperand/getLeftOperand: [LocalVariableAccess] var1 +# 67| getAnOperand/getRightOperand: [MethodCall] call to bar +# 67| getReceiver: [ConstantReadAccess] X +control/loops.rb: +# 10| [AssignExpr] ... = ... +# 10| getAnOperand/getLeftOperand: [LocalVariableAccess] sum +# 10| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 10| getAnOperand/getLeftOperand: [LocalVariableAccess] sum +# 10| getAnOperand/getRightOperand: [LocalVariableAccess] n +# 17| [AssignExpr] ... = ... +# 17| getAnOperand/getLeftOperand: [LocalVariableAccess] sum +# 17| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 17| getAnOperand/getLeftOperand: [LocalVariableAccess] sum +# 17| getAnOperand/getRightOperand: [LocalVariableAccess] n +# 18| [AssignExpr] ... = ... +# 18| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 18| getAnOperand/getRightOperand: [SubExpr] ... - ... +# 18| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 18| getAnOperand/getRightOperand: [LocalVariableAccess] n +# 23| [AssignExpr] ... = ... +# 23| getAnOperand/getLeftOperand: [LocalVariableAccess] sum +# 23| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 23| getAnOperand/getLeftOperand: [LocalVariableAccess] sum +# 23| getAnOperand/getRightOperand: [LocalVariableAccess] value +# 24| [AssignExpr] ... = ... +# 24| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 24| getAnOperand/getRightOperand: [MulExpr] ... * ... +# 24| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 24| getAnOperand/getRightOperand: [LocalVariableAccess] value +# 29| [AssignExpr] ... = ... +# 29| getAnOperand/getLeftOperand: [LocalVariableAccess] sum +# 29| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 29| getAnOperand/getLeftOperand: [LocalVariableAccess] sum +# 29| getAnOperand/getRightOperand: [LocalVariableAccess] value +# 30| [AssignExpr] ... = ... +# 30| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 30| getAnOperand/getRightOperand: [DivExpr] ... / ... +# 30| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 30| getAnOperand/getRightOperand: [LocalVariableAccess] value +# 36| [AssignExpr] ... = ... +# 36| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 36| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 36| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 36| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 37| [AssignExpr] ... = ... +# 37| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 37| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 37| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 37| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 43| [AssignExpr] ... = ... +# 43| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 43| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 43| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 43| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 44| [AssignExpr] ... = ... +# 44| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 44| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 44| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 44| getAnOperand/getRightOperand: [IntegerLiteral] 2 +# 48| [AssignExpr] ... = ... +# 48| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 48| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 48| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 48| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 52| [AssignExpr] ... = ... +# 52| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 52| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 52| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 52| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 53| [AssignExpr] ... = ... +# 53| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 53| getAnOperand/getRightOperand: [SubExpr] ... - ... +# 53| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 53| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 58| [AssignExpr] ... = ... +# 58| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 58| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 58| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 58| getAnOperand/getRightOperand: [IntegerLiteral] 1 +# 59| [AssignExpr] ... = ... +# 59| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 59| getAnOperand/getRightOperand: [SubExpr] ... - ... +# 59| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 59| getAnOperand/getRightOperand: [IntegerLiteral] 4 +# 63| [AssignExpr] ... = ... +# 63| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 63| getAnOperand/getRightOperand: [SubExpr] ... - ... +# 63| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 63| getAnOperand/getRightOperand: [IntegerLiteral] 1 +operations/operations.rb: +# 68| [AssignExpr] ... = ... +# 68| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 68| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 68| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 68| getAnOperand/getRightOperand: [IntegerLiteral] 128 +# 69| [AssignExpr] ... = ... +# 69| getAnOperand/getLeftOperand: [LocalVariableAccess] y +# 69| getAnOperand/getRightOperand: [SubExpr] ... - ... +# 69| getAnOperand/getLeftOperand: [LocalVariableAccess] y +# 69| getAnOperand/getRightOperand: [IntegerLiteral] 32 +# 70| [AssignExpr] ... = ... +# 70| getAnOperand/getLeftOperand: [LocalVariableAccess] a +# 70| getAnOperand/getRightOperand: [MulExpr] ... * ... +# 70| getAnOperand/getLeftOperand: [LocalVariableAccess] a +# 70| getAnOperand/getRightOperand: [IntegerLiteral] 12 +# 71| [AssignExpr] ... = ... +# 71| getAnOperand/getLeftOperand: [LocalVariableAccess] b +# 71| getAnOperand/getRightOperand: [DivExpr] ... / ... +# 71| getAnOperand/getLeftOperand: [LocalVariableAccess] b +# 71| getAnOperand/getRightOperand: [IntegerLiteral] 4 +# 72| [AssignExpr] ... = ... +# 72| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 72| getAnOperand/getRightOperand: [ModuloExpr] ... % ... +# 72| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 72| getAnOperand/getRightOperand: [IntegerLiteral] 2 +# 73| [AssignExpr] ... = ... +# 73| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 73| getAnOperand/getRightOperand: [ExponentExpr] ... ** ... +# 73| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 73| getAnOperand/getRightOperand: [LocalVariableAccess] bar +# 76| [AssignExpr] ... = ... +# 76| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 76| getAnOperand/getRightOperand: [LogicalAndExpr] ... && ... +# 76| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 76| getAnOperand/getRightOperand: [LocalVariableAccess] y +# 77| [AssignExpr] ... = ... +# 77| getAnOperand/getLeftOperand: [LocalVariableAccess] a +# 77| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... +# 77| getAnOperand/getLeftOperand: [LocalVariableAccess] a +# 77| getAnOperand/getRightOperand: [LocalVariableAccess] b +# 80| [AssignExpr] ... = ... +# 80| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 80| getAnOperand/getRightOperand: [LShiftExpr] ... << ... +# 80| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 80| getAnOperand/getRightOperand: [IntegerLiteral] 2 +# 81| [AssignExpr] ... = ... +# 81| getAnOperand/getLeftOperand: [LocalVariableAccess] y +# 81| getAnOperand/getRightOperand: [RShiftExpr] ... >> ... +# 81| getAnOperand/getLeftOperand: [LocalVariableAccess] y +# 81| getAnOperand/getRightOperand: [IntegerLiteral] 3 +# 82| [AssignExpr] ... = ... +# 82| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 82| getAnOperand/getRightOperand: [BitwiseAndExpr] ... & ... +# 82| getAnOperand/getLeftOperand: [LocalVariableAccess] foo +# 82| getAnOperand/getRightOperand: [LocalVariableAccess] mask +# 83| [AssignExpr] ... = ... +# 83| getAnOperand/getLeftOperand: [LocalVariableAccess] bar +# 83| getAnOperand/getRightOperand: [BitwiseOrExpr] ... | ... +# 83| getAnOperand/getLeftOperand: [LocalVariableAccess] bar +# 83| getAnOperand/getRightOperand: [IntegerLiteral] 0x01 +# 84| [AssignExpr] ... = ... +# 84| getAnOperand/getLeftOperand: [LocalVariableAccess] baz +# 84| getAnOperand/getRightOperand: [BitwiseXorExpr] ... ^ ... +# 84| getAnOperand/getLeftOperand: [LocalVariableAccess] baz +# 84| getAnOperand/getRightOperand: [LocalVariableAccess] qux +# 88| [AssignExpr] ... = ... +# 88| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x +# 88| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 88| getAnOperand/getLeftOperand: [InstanceVariableAccess] @x +# 88| getAnOperand/getRightOperand: [IntegerLiteral] 2 +# 91| [AssignExpr] ... = ... +# 91| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y +# 91| getAnOperand/getRightOperand: [DivExpr] ... / ... +# 91| getAnOperand/getLeftOperand: [ClassVariableAccess] @@y +# 91| getAnOperand/getRightOperand: [IntegerLiteral] 4 +# 95| [AssignExpr] ... = ... +# 95| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var +# 95| getAnOperand/getRightOperand: [MulExpr] ... * ... +# 95| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var +# 95| getAnOperand/getRightOperand: [IntegerLiteral] 6 diff --git a/ql/test/library-tests/ast/AstDesugar.ql b/ql/test/library-tests/ast/AstDesugar.ql new file mode 100644 index 00000000000..bad92ac1c35 --- /dev/null +++ b/ql/test/library-tests/ast/AstDesugar.ql @@ -0,0 +1,9 @@ +/** + * @kind graph + */ + +import codeql_ruby.printAst + +class DesugarPrintAstConfiguration extends PrintAstConfiguration { + override predicate shouldPrintNode(AstNode n) { isDesugared(n) } +} diff --git a/ql/test/library-tests/ast/operations/assignment.expected b/ql/test/library-tests/ast/operations/assignment.expected index 454f86743ba..e1a72d00e19 100644 --- a/ql/test/library-tests/ast/operations/assignment.expected +++ b/ql/test/library-tests/ast/operations/assignment.expected @@ -18,24 +18,40 @@ assignments | operations.rb:19:1:19:5 | ... = ... | = | operations.rb:19:1:19:1 | y | operations.rb:19:5:19:5 | 0 | AssignExpr | | operations.rb:20:1:20:5 | ... = ... | = | operations.rb:20:1:20:1 | z | operations.rb:20:5:20:5 | 0 | AssignExpr | | operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:1:68:1 | x | operations.rb:68:6:68:8 | 128 | AssignAddExpr | +| operations.rb:68:1:68:8 | ... = ... | = | operations.rb:68:1:68:1 | x | operations.rb:68:1:68:8 | ... + ... | AssignExpr | | operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:1:69:1 | y | operations.rb:69:6:69:7 | 32 | AssignSubExpr | +| operations.rb:69:1:69:7 | ... = ... | = | operations.rb:69:1:69:1 | y | operations.rb:69:1:69:7 | ... - ... | AssignExpr | | operations.rb:70:1:70:7 | ... *= ... | *= | operations.rb:70:1:70:1 | a | operations.rb:70:6:70:7 | 12 | AssignMulExpr | +| operations.rb:70:1:70:7 | ... = ... | = | operations.rb:70:1:70:1 | a | operations.rb:70:1:70:7 | ... * ... | AssignExpr | | operations.rb:71:1:71:6 | ... /= ... | /= | operations.rb:71:1:71:1 | b | operations.rb:71:6:71:6 | 4 | AssignDivExpr | +| operations.rb:71:1:71:6 | ... = ... | = | operations.rb:71:1:71:1 | b | operations.rb:71:1:71:6 | ... / ... | AssignExpr | | operations.rb:72:1:72:6 | ... %= ... | %= | operations.rb:72:1:72:1 | z | operations.rb:72:6:72:6 | 2 | AssignModuloExpr | +| operations.rb:72:1:72:6 | ... = ... | = | operations.rb:72:1:72:1 | z | operations.rb:72:1:72:6 | ... % ... | AssignExpr | | operations.rb:73:1:73:11 | ... **= ... | **= | operations.rb:73:1:73:3 | foo | operations.rb:73:9:73:11 | bar | AssignExponentExpr | +| operations.rb:73:1:73:11 | ... = ... | = | operations.rb:73:1:73:3 | foo | operations.rb:73:1:73:11 | ... ** ... | AssignExpr | | operations.rb:76:2:76:8 | ... &&= ... | &&= | operations.rb:76:2:76:2 | x | operations.rb:76:8:76:8 | y | AssignLogicalAndExpr | +| operations.rb:76:2:76:8 | ... = ... | = | operations.rb:76:2:76:2 | x | operations.rb:76:2:76:8 | ... && ... | AssignExpr | +| operations.rb:77:2:77:8 | ... = ... | = | operations.rb:77:2:77:2 | a | operations.rb:77:2:77:8 | ... \|\| ... | AssignExpr | | operations.rb:77:2:77:8 | ... \|\|= ... | \|\|= | operations.rb:77:2:77:2 | a | operations.rb:77:8:77:8 | b | AssignLogicalOrExpr | | operations.rb:80:2:80:8 | ... <<= ... | <<= | operations.rb:80:2:80:2 | x | operations.rb:80:8:80:8 | 2 | AssignLShiftExpr | +| operations.rb:80:2:80:8 | ... = ... | = | operations.rb:80:2:80:2 | x | operations.rb:80:2:80:8 | ... << ... | AssignExpr | +| operations.rb:81:2:81:8 | ... = ... | = | operations.rb:81:2:81:2 | y | operations.rb:81:2:81:8 | ... >> ... | AssignExpr | | operations.rb:81:2:81:8 | ... >>= ... | >>= | operations.rb:81:2:81:2 | y | operations.rb:81:8:81:8 | 3 | AssignRShiftExpr | | operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:2:82:4 | foo | operations.rb:82:9:82:12 | mask | AssignBitwiseAndExpr | +| operations.rb:82:2:82:12 | ... = ... | = | operations.rb:82:2:82:4 | foo | operations.rb:82:2:82:12 | ... & ... | AssignExpr | +| operations.rb:83:2:83:12 | ... = ... | = | operations.rb:83:2:83:4 | bar | operations.rb:83:2:83:12 | ... \| ... | AssignExpr | | operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:2:83:4 | bar | operations.rb:83:9:83:12 | 0x01 | AssignBitwiseOrExpr | +| operations.rb:84:2:84:11 | ... = ... | = | operations.rb:84:2:84:4 | baz | operations.rb:84:2:84:11 | ... ^ ... | AssignExpr | | operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:2:84:4 | baz | operations.rb:84:9:84:11 | qux | AssignBitwiseXorExpr | | operations.rb:87:3:87:8 | ... = ... | = | operations.rb:87:3:87:4 | @x | operations.rb:87:8:87:8 | 1 | AssignExpr | | operations.rb:88:3:88:9 | ... += ... | += | operations.rb:88:3:88:4 | @x | operations.rb:88:9:88:9 | 2 | AssignAddExpr | +| operations.rb:88:3:88:9 | ... = ... | = | operations.rb:88:3:88:4 | @x | operations.rb:88:3:88:9 | ... + ... | AssignExpr | | operations.rb:90:3:90:9 | ... = ... | = | operations.rb:90:3:90:5 | @@y | operations.rb:90:9:90:9 | 3 | AssignExpr | | operations.rb:91:3:91:10 | ... /= ... | /= | operations.rb:91:3:91:5 | @@y | operations.rb:91:10:91:10 | 4 | AssignDivExpr | +| operations.rb:91:3:91:10 | ... = ... | = | operations.rb:91:3:91:5 | @@y | operations.rb:91:3:91:10 | ... / ... | AssignExpr | | operations.rb:94:1:94:15 | ... = ... | = | operations.rb:94:1:94:11 | $global_var | operations.rb:94:15:94:15 | 5 | AssignExpr | | operations.rb:95:1:95:16 | ... *= ... | *= | operations.rb:95:1:95:11 | $global_var | operations.rb:95:16:95:16 | 6 | AssignMulExpr | +| operations.rb:95:1:95:16 | ... = ... | = | operations.rb:95:1:95:11 | $global_var | operations.rb:95:1:95:16 | ... * ... | AssignExpr | assignOperations | operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:1:68:1 | x | operations.rb:68:6:68:8 | 128 | AssignAddExpr | | operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:1:69:1 | y | operations.rb:69:6:69:7 | 32 | AssignSubExpr | diff --git a/ql/test/library-tests/ast/operations/binary.expected b/ql/test/library-tests/ast/operations/binary.expected index e59833bd54a..998d2cc343f 100644 --- a/ql/test/library-tests/ast/operations/binary.expected +++ b/ql/test/library-tests/ast/operations/binary.expected @@ -24,6 +24,22 @@ binaryOperations | operations.rb:63:1:63:7 | ... <=> ... | <=> | operations.rb:63:1:63:1 | a | operations.rb:63:7:63:7 | b | SpaceshipExpr | | operations.rb:64:1:64:15 | ... =~ ... | =~ | operations.rb:64:1:64:4 | name | operations.rb:64:9:64:15 | /foo.*/ | RegexMatchExpr | | operations.rb:65:1:65:17 | ... !~ ... | !~ | operations.rb:65:1:65:6 | handle | operations.rb:65:11:65:17 | /.*bar/ | NoRegexMatchExpr | +| operations.rb:68:1:68:8 | ... + ... | + | operations.rb:68:1:68:8 | x | operations.rb:68:6:68:8 | 128 | AddExpr | +| operations.rb:69:1:69:7 | ... - ... | - | operations.rb:69:1:69:7 | y | operations.rb:69:6:69:7 | 32 | SubExpr | +| operations.rb:70:1:70:7 | ... * ... | * | operations.rb:70:1:70:7 | a | operations.rb:70:6:70:7 | 12 | MulExpr | +| operations.rb:71:1:71:6 | ... / ... | / | operations.rb:71:1:71:6 | b | operations.rb:71:6:71:6 | 4 | DivExpr | +| operations.rb:72:1:72:6 | ... % ... | % | operations.rb:72:1:72:6 | z | operations.rb:72:6:72:6 | 2 | ModuloExpr | +| operations.rb:73:1:73:11 | ... ** ... | ** | operations.rb:73:1:73:11 | foo | operations.rb:73:9:73:11 | bar | ExponentExpr | +| operations.rb:76:2:76:8 | ... && ... | && | operations.rb:76:2:76:8 | x | operations.rb:76:8:76:8 | y | LogicalAndExpr | +| operations.rb:77:2:77:8 | ... \|\| ... | \|\| | operations.rb:77:2:77:8 | a | operations.rb:77:8:77:8 | b | LogicalOrExpr | +| operations.rb:80:2:80:8 | ... << ... | << | operations.rb:80:2:80:8 | x | operations.rb:80:8:80:8 | 2 | LShiftExpr | +| operations.rb:81:2:81:8 | ... >> ... | >> | operations.rb:81:2:81:8 | y | operations.rb:81:8:81:8 | 3 | RShiftExpr | +| operations.rb:82:2:82:12 | ... & ... | & | operations.rb:82:2:82:12 | foo | operations.rb:82:9:82:12 | mask | BitwiseAndExpr | +| operations.rb:83:2:83:12 | ... \| ... | \| | operations.rb:83:2:83:12 | bar | operations.rb:83:9:83:12 | 0x01 | BitwiseOrExpr | +| operations.rb:84:2:84:11 | ... ^ ... | ^ | operations.rb:84:2:84:11 | baz | operations.rb:84:9:84:11 | qux | BitwiseXorExpr | +| operations.rb:88:3:88:9 | ... + ... | + | operations.rb:88:3:88:9 | @x | operations.rb:88:9:88:9 | 2 | AddExpr | +| operations.rb:91:3:91:10 | ... / ... | / | operations.rb:91:3:91:10 | @@y | operations.rb:91:10:91:10 | 4 | DivExpr | +| operations.rb:95:1:95:16 | ... * ... | * | operations.rb:95:1:95:16 | $global_var | operations.rb:95:16:95:16 | 6 | MulExpr | binaryArithmeticOperations | operations.rb:31:1:31:7 | ... + ... | + | operations.rb:31:1:31:1 | w | operations.rb:31:5:31:7 | 234 | AddExpr | | operations.rb:32:1:32:6 | ... - ... | - | operations.rb:32:1:32:1 | x | operations.rb:32:5:32:6 | 17 | SubExpr | @@ -31,17 +47,33 @@ binaryArithmeticOperations | operations.rb:34:1:34:5 | ... / ... | / | operations.rb:34:1:34:1 | z | operations.rb:34:5:34:5 | 2 | DivExpr | | operations.rb:35:1:35:7 | ... % ... | % | operations.rb:35:1:35:3 | num | operations.rb:35:7:35:7 | 2 | ModuloExpr | | operations.rb:36:1:36:13 | ... ** ... | ** | operations.rb:36:1:36:4 | base | operations.rb:36:9:36:13 | power | ExponentExpr | +| operations.rb:68:1:68:8 | ... + ... | + | operations.rb:68:1:68:8 | x | operations.rb:68:6:68:8 | 128 | AddExpr | +| operations.rb:69:1:69:7 | ... - ... | - | operations.rb:69:1:69:7 | y | operations.rb:69:6:69:7 | 32 | SubExpr | +| operations.rb:70:1:70:7 | ... * ... | * | operations.rb:70:1:70:7 | a | operations.rb:70:6:70:7 | 12 | MulExpr | +| operations.rb:71:1:71:6 | ... / ... | / | operations.rb:71:1:71:6 | b | operations.rb:71:6:71:6 | 4 | DivExpr | +| operations.rb:72:1:72:6 | ... % ... | % | operations.rb:72:1:72:6 | z | operations.rb:72:6:72:6 | 2 | ModuloExpr | +| operations.rb:73:1:73:11 | ... ** ... | ** | operations.rb:73:1:73:11 | foo | operations.rb:73:9:73:11 | bar | ExponentExpr | +| operations.rb:88:3:88:9 | ... + ... | + | operations.rb:88:3:88:9 | @x | operations.rb:88:9:88:9 | 2 | AddExpr | +| operations.rb:91:3:91:10 | ... / ... | / | operations.rb:91:3:91:10 | @@y | operations.rb:91:10:91:10 | 4 | DivExpr | +| operations.rb:95:1:95:16 | ... * ... | * | operations.rb:95:1:95:16 | $global_var | operations.rb:95:16:95:16 | 6 | MulExpr | binaryLogicalOperations | operations.rb:39:1:39:10 | ... && ... | && | operations.rb:39:1:39:3 | foo | operations.rb:39:8:39:10 | bar | LogicalAndExpr | | operations.rb:40:1:40:11 | ... and ... | and | operations.rb:40:1:40:3 | baz | operations.rb:40:9:40:11 | qux | LogicalAndExpr | | operations.rb:41:1:41:6 | ... or ... | or | operations.rb:41:1:41:1 | a | operations.rb:41:6:41:6 | b | LogicalOrExpr | | operations.rb:42:1:42:6 | ... \|\| ... | \|\| | operations.rb:42:1:42:1 | x | operations.rb:42:6:42:6 | y | LogicalOrExpr | +| operations.rb:76:2:76:8 | ... && ... | && | operations.rb:76:2:76:8 | x | operations.rb:76:8:76:8 | y | LogicalAndExpr | +| operations.rb:77:2:77:8 | ... \|\| ... | \|\| | operations.rb:77:2:77:8 | a | operations.rb:77:8:77:8 | b | LogicalOrExpr | binaryBitwiseOperations | operations.rb:45:1:45:6 | ... << ... | << | operations.rb:45:1:45:1 | x | operations.rb:45:6:45:6 | 3 | LShiftExpr | | operations.rb:46:1:46:7 | ... >> ... | >> | operations.rb:46:1:46:1 | y | operations.rb:46:6:46:7 | 16 | RShiftExpr | | operations.rb:47:1:47:10 | ... & ... | & | operations.rb:47:1:47:3 | foo | operations.rb:47:7:47:10 | 0xff | BitwiseAndExpr | | operations.rb:48:1:48:10 | ... \| ... | \| | operations.rb:48:1:48:3 | bar | operations.rb:48:7:48:10 | 0x02 | BitwiseOrExpr | | operations.rb:49:1:49:9 | ... ^ ... | ^ | operations.rb:49:1:49:3 | baz | operations.rb:49:7:49:9 | qux | BitwiseXorExpr | +| operations.rb:80:2:80:8 | ... << ... | << | operations.rb:80:2:80:8 | x | operations.rb:80:8:80:8 | 2 | LShiftExpr | +| operations.rb:81:2:81:8 | ... >> ... | >> | operations.rb:81:2:81:8 | y | operations.rb:81:8:81:8 | 3 | RShiftExpr | +| operations.rb:82:2:82:12 | ... & ... | & | operations.rb:82:2:82:12 | foo | operations.rb:82:9:82:12 | mask | BitwiseAndExpr | +| operations.rb:83:2:83:12 | ... \| ... | \| | operations.rb:83:2:83:12 | bar | operations.rb:83:9:83:12 | 0x01 | BitwiseOrExpr | +| operations.rb:84:2:84:11 | ... ^ ... | ^ | operations.rb:84:2:84:11 | baz | operations.rb:84:9:84:11 | qux | BitwiseXorExpr | comparisonOperations | operations.rb:52:1:52:6 | ... == ... | == | operations.rb:52:1:52:1 | x | operations.rb:52:6:52:6 | y | EqExpr | | operations.rb:53:1:53:8 | ... != ... | != | operations.rb:53:1:53:1 | a | operations.rb:53:6:53:8 | 123 | NEExpr | diff --git a/ql/test/library-tests/ast/operations/operation.expected b/ql/test/library-tests/ast/operations/operation.expected index 7f4d25068eb..86818353455 100644 --- a/ql/test/library-tests/ast/operations/operation.expected +++ b/ql/test/library-tests/ast/operations/operation.expected @@ -90,41 +90,105 @@ | operations.rb:64:1:64:15 | ... =~ ... | =~ | operations.rb:64:9:64:15 | /foo.*/ | RegexMatchExpr | | operations.rb:65:1:65:17 | ... !~ ... | !~ | operations.rb:65:1:65:6 | handle | NoRegexMatchExpr | | operations.rb:65:1:65:17 | ... !~ ... | !~ | operations.rb:65:11:65:17 | /.*bar/ | NoRegexMatchExpr | +| operations.rb:68:1:68:8 | ... + ... | + | operations.rb:68:1:68:8 | x | AddExpr | +| operations.rb:68:1:68:8 | ... + ... | + | operations.rb:68:6:68:8 | 128 | AddExpr | | operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:1:68:1 | x | AssignAddExpr | | operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:6:68:8 | 128 | AssignAddExpr | +| operations.rb:68:1:68:8 | ... = ... | = | operations.rb:68:1:68:1 | x | AssignExpr | +| operations.rb:68:1:68:8 | ... = ... | = | operations.rb:68:1:68:8 | ... + ... | AssignExpr | +| operations.rb:69:1:69:7 | ... - ... | - | operations.rb:69:1:69:7 | y | SubExpr | +| operations.rb:69:1:69:7 | ... - ... | - | operations.rb:69:6:69:7 | 32 | SubExpr | | operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:1:69:1 | y | AssignSubExpr | | operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:6:69:7 | 32 | AssignSubExpr | +| operations.rb:69:1:69:7 | ... = ... | = | operations.rb:69:1:69:1 | y | AssignExpr | +| operations.rb:69:1:69:7 | ... = ... | = | operations.rb:69:1:69:7 | ... - ... | AssignExpr | +| operations.rb:70:1:70:7 | ... * ... | * | operations.rb:70:1:70:7 | a | MulExpr | +| operations.rb:70:1:70:7 | ... * ... | * | operations.rb:70:6:70:7 | 12 | MulExpr | | operations.rb:70:1:70:7 | ... *= ... | *= | operations.rb:70:1:70:1 | a | AssignMulExpr | | operations.rb:70:1:70:7 | ... *= ... | *= | operations.rb:70:6:70:7 | 12 | AssignMulExpr | +| operations.rb:70:1:70:7 | ... = ... | = | operations.rb:70:1:70:1 | a | AssignExpr | +| operations.rb:70:1:70:7 | ... = ... | = | operations.rb:70:1:70:7 | ... * ... | AssignExpr | +| operations.rb:71:1:71:6 | ... / ... | / | operations.rb:71:1:71:6 | b | DivExpr | +| operations.rb:71:1:71:6 | ... / ... | / | operations.rb:71:6:71:6 | 4 | DivExpr | | operations.rb:71:1:71:6 | ... /= ... | /= | operations.rb:71:1:71:1 | b | AssignDivExpr | | operations.rb:71:1:71:6 | ... /= ... | /= | operations.rb:71:6:71:6 | 4 | AssignDivExpr | +| operations.rb:71:1:71:6 | ... = ... | = | operations.rb:71:1:71:1 | b | AssignExpr | +| operations.rb:71:1:71:6 | ... = ... | = | operations.rb:71:1:71:6 | ... / ... | AssignExpr | +| operations.rb:72:1:72:6 | ... % ... | % | operations.rb:72:1:72:6 | z | ModuloExpr | +| operations.rb:72:1:72:6 | ... % ... | % | operations.rb:72:6:72:6 | 2 | ModuloExpr | | operations.rb:72:1:72:6 | ... %= ... | %= | operations.rb:72:1:72:1 | z | AssignModuloExpr | | operations.rb:72:1:72:6 | ... %= ... | %= | operations.rb:72:6:72:6 | 2 | AssignModuloExpr | +| operations.rb:72:1:72:6 | ... = ... | = | operations.rb:72:1:72:1 | z | AssignExpr | +| operations.rb:72:1:72:6 | ... = ... | = | operations.rb:72:1:72:6 | ... % ... | AssignExpr | +| operations.rb:73:1:73:11 | ... ** ... | ** | operations.rb:73:1:73:11 | foo | ExponentExpr | +| operations.rb:73:1:73:11 | ... ** ... | ** | operations.rb:73:9:73:11 | bar | ExponentExpr | | operations.rb:73:1:73:11 | ... **= ... | **= | operations.rb:73:1:73:3 | foo | AssignExponentExpr | | operations.rb:73:1:73:11 | ... **= ... | **= | operations.rb:73:9:73:11 | bar | AssignExponentExpr | +| operations.rb:73:1:73:11 | ... = ... | = | operations.rb:73:1:73:3 | foo | AssignExpr | +| operations.rb:73:1:73:11 | ... = ... | = | operations.rb:73:1:73:11 | ... ** ... | AssignExpr | +| operations.rb:76:2:76:8 | ... && ... | && | operations.rb:76:2:76:8 | x | LogicalAndExpr | +| operations.rb:76:2:76:8 | ... && ... | && | operations.rb:76:8:76:8 | y | LogicalAndExpr | | operations.rb:76:2:76:8 | ... &&= ... | &&= | operations.rb:76:2:76:2 | x | AssignLogicalAndExpr | | operations.rb:76:2:76:8 | ... &&= ... | &&= | operations.rb:76:8:76:8 | y | AssignLogicalAndExpr | +| operations.rb:76:2:76:8 | ... = ... | = | operations.rb:76:2:76:2 | x | AssignExpr | +| operations.rb:76:2:76:8 | ... = ... | = | operations.rb:76:2:76:8 | ... && ... | AssignExpr | +| operations.rb:77:2:77:8 | ... = ... | = | operations.rb:77:2:77:2 | a | AssignExpr | +| operations.rb:77:2:77:8 | ... = ... | = | operations.rb:77:2:77:8 | ... \|\| ... | AssignExpr | +| operations.rb:77:2:77:8 | ... \|\| ... | \|\| | operations.rb:77:2:77:8 | a | LogicalOrExpr | +| operations.rb:77:2:77:8 | ... \|\| ... | \|\| | operations.rb:77:8:77:8 | b | LogicalOrExpr | | operations.rb:77:2:77:8 | ... \|\|= ... | \|\|= | operations.rb:77:2:77:2 | a | AssignLogicalOrExpr | | operations.rb:77:2:77:8 | ... \|\|= ... | \|\|= | operations.rb:77:8:77:8 | b | AssignLogicalOrExpr | +| operations.rb:80:2:80:8 | ... << ... | << | operations.rb:80:2:80:8 | x | LShiftExpr | +| operations.rb:80:2:80:8 | ... << ... | << | operations.rb:80:8:80:8 | 2 | LShiftExpr | | operations.rb:80:2:80:8 | ... <<= ... | <<= | operations.rb:80:2:80:2 | x | AssignLShiftExpr | | operations.rb:80:2:80:8 | ... <<= ... | <<= | operations.rb:80:8:80:8 | 2 | AssignLShiftExpr | +| operations.rb:80:2:80:8 | ... = ... | = | operations.rb:80:2:80:2 | x | AssignExpr | +| operations.rb:80:2:80:8 | ... = ... | = | operations.rb:80:2:80:8 | ... << ... | AssignExpr | +| operations.rb:81:2:81:8 | ... = ... | = | operations.rb:81:2:81:2 | y | AssignExpr | +| operations.rb:81:2:81:8 | ... = ... | = | operations.rb:81:2:81:8 | ... >> ... | AssignExpr | +| operations.rb:81:2:81:8 | ... >> ... | >> | operations.rb:81:2:81:8 | y | RShiftExpr | +| operations.rb:81:2:81:8 | ... >> ... | >> | operations.rb:81:8:81:8 | 3 | RShiftExpr | | operations.rb:81:2:81:8 | ... >>= ... | >>= | operations.rb:81:2:81:2 | y | AssignRShiftExpr | | operations.rb:81:2:81:8 | ... >>= ... | >>= | operations.rb:81:8:81:8 | 3 | AssignRShiftExpr | +| operations.rb:82:2:82:12 | ... & ... | & | operations.rb:82:2:82:12 | foo | BitwiseAndExpr | +| operations.rb:82:2:82:12 | ... & ... | & | operations.rb:82:9:82:12 | mask | BitwiseAndExpr | | operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:2:82:4 | foo | AssignBitwiseAndExpr | | operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:9:82:12 | mask | AssignBitwiseAndExpr | +| operations.rb:82:2:82:12 | ... = ... | = | operations.rb:82:2:82:4 | foo | AssignExpr | +| operations.rb:82:2:82:12 | ... = ... | = | operations.rb:82:2:82:12 | ... & ... | AssignExpr | +| operations.rb:83:2:83:12 | ... = ... | = | operations.rb:83:2:83:4 | bar | AssignExpr | +| operations.rb:83:2:83:12 | ... = ... | = | operations.rb:83:2:83:12 | ... \| ... | AssignExpr | +| operations.rb:83:2:83:12 | ... \| ... | \| | operations.rb:83:2:83:12 | bar | BitwiseOrExpr | +| operations.rb:83:2:83:12 | ... \| ... | \| | operations.rb:83:9:83:12 | 0x01 | BitwiseOrExpr | | operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:2:83:4 | bar | AssignBitwiseOrExpr | | operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:9:83:12 | 0x01 | AssignBitwiseOrExpr | +| operations.rb:84:2:84:11 | ... = ... | = | operations.rb:84:2:84:4 | baz | AssignExpr | +| operations.rb:84:2:84:11 | ... = ... | = | operations.rb:84:2:84:11 | ... ^ ... | AssignExpr | +| operations.rb:84:2:84:11 | ... ^ ... | ^ | operations.rb:84:2:84:11 | baz | BitwiseXorExpr | +| operations.rb:84:2:84:11 | ... ^ ... | ^ | operations.rb:84:9:84:11 | qux | BitwiseXorExpr | | operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:2:84:4 | baz | AssignBitwiseXorExpr | | operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:9:84:11 | qux | AssignBitwiseXorExpr | | operations.rb:87:3:87:8 | ... = ... | = | operations.rb:87:3:87:4 | @x | AssignExpr | | operations.rb:87:3:87:8 | ... = ... | = | operations.rb:87:8:87:8 | 1 | AssignExpr | +| operations.rb:88:3:88:9 | ... + ... | + | operations.rb:88:3:88:9 | @x | AddExpr | +| operations.rb:88:3:88:9 | ... + ... | + | operations.rb:88:9:88:9 | 2 | AddExpr | | operations.rb:88:3:88:9 | ... += ... | += | operations.rb:88:3:88:4 | @x | AssignAddExpr | | operations.rb:88:3:88:9 | ... += ... | += | operations.rb:88:9:88:9 | 2 | AssignAddExpr | +| operations.rb:88:3:88:9 | ... = ... | = | operations.rb:88:3:88:4 | @x | AssignExpr | +| operations.rb:88:3:88:9 | ... = ... | = | operations.rb:88:3:88:9 | ... + ... | AssignExpr | | operations.rb:90:3:90:9 | ... = ... | = | operations.rb:90:3:90:5 | @@y | AssignExpr | | operations.rb:90:3:90:9 | ... = ... | = | operations.rb:90:9:90:9 | 3 | AssignExpr | +| operations.rb:91:3:91:10 | ... / ... | / | operations.rb:91:3:91:10 | @@y | DivExpr | +| operations.rb:91:3:91:10 | ... / ... | / | operations.rb:91:10:91:10 | 4 | DivExpr | | operations.rb:91:3:91:10 | ... /= ... | /= | operations.rb:91:3:91:5 | @@y | AssignDivExpr | | operations.rb:91:3:91:10 | ... /= ... | /= | operations.rb:91:10:91:10 | 4 | AssignDivExpr | +| operations.rb:91:3:91:10 | ... = ... | = | operations.rb:91:3:91:5 | @@y | AssignExpr | +| operations.rb:91:3:91:10 | ... = ... | = | operations.rb:91:3:91:10 | ... / ... | AssignExpr | | operations.rb:94:1:94:15 | ... = ... | = | operations.rb:94:1:94:11 | $global_var | AssignExpr | | operations.rb:94:1:94:15 | ... = ... | = | operations.rb:94:15:94:15 | 5 | AssignExpr | +| operations.rb:95:1:95:16 | ... * ... | * | operations.rb:95:1:95:16 | $global_var | MulExpr | +| operations.rb:95:1:95:16 | ... * ... | * | operations.rb:95:16:95:16 | 6 | MulExpr | | operations.rb:95:1:95:16 | ... *= ... | *= | operations.rb:95:1:95:11 | $global_var | AssignMulExpr | | operations.rb:95:1:95:16 | ... *= ... | *= | operations.rb:95:16:95:16 | 6 | AssignMulExpr | +| operations.rb:95:1:95:16 | ... = ... | = | operations.rb:95:1:95:11 | $global_var | AssignExpr | +| operations.rb:95:1:95:16 | ... = ... | = | operations.rb:95:1:95:16 | ... * ... | AssignExpr | diff --git a/ql/test/library-tests/controlflow/graph/Cfg.expected b/ql/test/library-tests/controlflow/graph/Cfg.expected index 84e66808854..416921e9866 100644 --- a/ql/test/library-tests/controlflow/graph/Cfg.expected +++ b/ql/test/library-tests/controlflow/graph/Cfg.expected @@ -687,12 +687,12 @@ cfg.rb: # 35| false #-----| false -> if ... -# 39| self -#-----| -> 42 - # 39| call to puts #-----| -> case ... +# 39| self +#-----| -> 42 + # 39| 42 #-----| -> call to puts @@ -1444,14 +1444,20 @@ cfg.rb: # 124| 2 #-----| -> ... = ... -# 125| ... += ... +# 125| some +#-----| -> some + +# 125| ... = ... #-----| -> last +# 125| ... + ... +#-----| -> ... = ... + # 125| some #-----| -> 10 # 125| 10 -#-----| -> ... += ... +#-----| -> ... + ... # 126| ... = ... #-----| -> range @@ -1544,8 +1550,8 @@ cfg.rb: #-----| -> ... rescue ... # 136| ... / ... -#-----| raise -> self #-----| -> init +#-----| raise -> self # 136| 1 #-----| -> 0 @@ -1880,14 +1886,20 @@ cfg.rb: # 176| do ... #-----| -> x -# 176| ... += ... +# 176| x +#-----| -> x + +# 176| ... = ... #-----| -> self +# 176| ... + ... +#-----| -> ... = ... + # 176| x #-----| -> 10 # 176| 10 -#-----| -> ... += ... +#-----| -> ... + ... # 176| call to puts #-----| -> x @@ -1922,14 +1934,20 @@ cfg.rb: # 179| "hello" #-----| -> call to puts -# 179| ... += ... +# 179| i +#-----| -> i + +# 179| ... = ... #-----| -> ( ... ) +# 179| ... + ... +#-----| -> ... = ... + # 179| i #-----| -> 1 # 179| 1 -#-----| -> ... += ... +#-----| -> ... + ... # 179| ... == ... #-----| true -> ... until ... @@ -1966,14 +1984,20 @@ cfg.rb: # 182| do ... #-----| -> x -# 183| ... += ... +# 183| x #-----| -> x +# 183| ... = ... +#-----| -> x + +# 183| ... + ... +#-----| -> ... = ... + # 183| x #-----| -> 1 # 183| 1 -#-----| -> ... += ... +#-----| -> ... + ... # 184| if ... #-----| -> self @@ -2018,14 +2042,20 @@ cfg.rb: # 188| "hello" #-----| -> call to puts -# 188| ... -= ... +# 188| i +#-----| -> i + +# 188| ... = ... #-----| -> ( ... ) +# 188| ... - ... +#-----| -> ... = ... + # 188| i #-----| -> 1 # 188| 1 -#-----| -> ... -= ... +#-----| -> ... - ... # 188| ... != ... #-----| false -> ... while ... @@ -2106,14 +2136,20 @@ desugar.rb: # 1| x #-----| -> x -# 2| ... += ... +# 2| x +#-----| -> x + +# 2| ... = ... #-----| -> exit m1 (normal) +# 2| ... + ... +#-----| -> ... = ... + # 2| x #-----| -> 1 # 2| 1 -#-----| -> ... += ... +#-----| -> ... + ... # 5| enter m2 #-----| -> x @@ -2209,14 +2245,20 @@ desugar.rb: # 14| 1 #-----| -> ... = ... -# 15| ... += ... +# 15| @x +#-----| -> @x + +# 15| ... = ... #-----| -> @@y +# 15| ... + ... +#-----| -> ... = ... + # 15| @x #-----| -> 2 # 15| 2 -#-----| -> ... += ... +#-----| -> ... + ... # 17| ... = ... #-----| -> @@y @@ -2227,14 +2269,20 @@ desugar.rb: # 17| 3 #-----| -> ... = ... -# 18| ... /= ... +# 18| @@y +#-----| -> @@y + +# 18| ... = ... #-----| -> $global_var +# 18| ... / ... +#-----| -> ... = ... + # 18| @@y #-----| -> 4 # 18| 4 -#-----| -> ... /= ... +#-----| -> ... / ... # 21| ... = ... #-----| -> $global_var @@ -2245,14 +2293,20 @@ desugar.rb: # 21| 5 #-----| -> ... = ... -# 22| ... *= ... +# 22| $global_var +#-----| -> $global_var + +# 22| ... = ... #-----| -> exit desugar.rb (normal) +# 22| ... * ... +#-----| -> ... = ... + # 22| $global_var #-----| -> 6 # 22| 6 -#-----| -> ... *= ... +#-----| -> ... * ... exit.rb: # 1| enter m1 @@ -2934,14 +2988,20 @@ loops.rb: # 3| x #-----| -> call to puts -# 4| ... -= ... +# 4| x #-----| -> x +# 4| ... = ... +#-----| -> x + +# 4| ... - ... +#-----| -> ... = ... + # 4| x #-----| -> 1 # 4| 1 -#-----| -> ... -= ... +#-----| -> ... - ... # 8| enter m2 #-----| -> x @@ -2982,14 +3042,20 @@ loops.rb: # 10| x #-----| -> call to puts -# 11| ... -= ... +# 11| x #-----| -> x +# 11| ... = ... +#-----| -> x + +# 11| ... - ... +#-----| -> ... = ... + # 11| x #-----| -> 1 # 11| 1 -#-----| -> ... -= ... +#-----| -> ... - ... # 12| if ... #-----| -> self diff --git a/ql/test/library-tests/controlflow/graph/Cfg.ql b/ql/test/library-tests/controlflow/graph/Cfg.ql new file mode 100644 index 00000000000..2217d9dba83 --- /dev/null +++ b/ql/test/library-tests/controlflow/graph/Cfg.ql @@ -0,0 +1,9 @@ +/** + * @kind graph + */ + +import codeql_ruby.controlflow.internal.Cfg + +class MyRelevantCfgNode extends RelevantCfgNode { + MyRelevantCfgNode() { exists(this) } +} diff --git a/ql/test/library-tests/controlflow/graph/Cfg.qlref b/ql/test/library-tests/controlflow/graph/Cfg.qlref deleted file mode 100644 index fb0ac5085b2..00000000000 --- a/ql/test/library-tests/controlflow/graph/Cfg.qlref +++ /dev/null @@ -1 +0,0 @@ -codeql_ruby/controlflow/internal/Cfg.ql \ No newline at end of file diff --git a/ql/test/library-tests/dataflow/local/DataflowStep.expected b/ql/test/library-tests/dataflow/local/DataflowStep.expected index a41b0df807f..2fc9deb8962 100644 --- a/ql/test/library-tests/dataflow/local/DataflowStep.expected +++ b/ql/test/library-tests/dataflow/local/DataflowStep.expected @@ -14,9 +14,10 @@ | local_dataflow.rb:5:7:5:13 | ( ... ) | local_dataflow.rb:5:3:5:13 | ... = ... | | local_dataflow.rb:5:8:5:12 | ... = ... | local_dataflow.rb:5:7:5:13 | ( ... ) | | local_dataflow.rb:5:12:5:12 | a | local_dataflow.rb:5:8:5:12 | ... = ... | -| local_dataflow.rb:5:12:5:12 | a | local_dataflow.rb:6:8:6:8 | a | +| local_dataflow.rb:5:12:5:12 | a | local_dataflow.rb:6:8:6:13 | a | | local_dataflow.rb:6:7:6:14 | ( ... ) | local_dataflow.rb:6:3:6:14 | ... = ... | -| local_dataflow.rb:6:8:6:13 | ... += ... | local_dataflow.rb:6:7:6:14 | ( ... ) | +| local_dataflow.rb:6:8:6:13 | ... + ... | local_dataflow.rb:6:8:6:13 | ... = ... | +| local_dataflow.rb:6:8:6:13 | ... = ... | local_dataflow.rb:6:7:6:14 | ( ... ) | | local_dataflow.rb:9:1:9:15 | ... = ... | local_dataflow.rb:10:14:10:18 | array | | local_dataflow.rb:9:9:9:15 | [...] | local_dataflow.rb:9:1:9:15 | ... = ... | | local_dataflow.rb:9:9:9:15 | [...] | local_dataflow.rb:9:1:9:15 | ... = ... | diff --git a/ql/test/library-tests/variables/ssa.expected b/ql/test/library-tests/variables/ssa.expected index f6aad2b343d..032dd9d9699 100644 --- a/ql/test/library-tests/variables/ssa.expected +++ b/ql/test/library-tests/variables/ssa.expected @@ -42,7 +42,7 @@ definition | scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | | scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | | scopes.rb:9:9:18:3 | | scopes.rb:7:1:7:1 | a | -| scopes.rb:11:4:11:9 | ... += ... | scopes.rb:7:1:7:1 | a | +| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:7:1:7:1 | a | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:7:13:7 | b | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:11:13:11 | c | @@ -55,7 +55,7 @@ definition | ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | | ssa.rb:18:8:18:8 | x | ssa.rb:18:8:18:8 | x | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | -| ssa.rb:21:5:21:10 | ... -= ... | ssa.rb:18:8:18:8 | x | +| ssa.rb:21:5:21:10 | ... = ... | ssa.rb:18:8:18:8 | x | | ssa.rb:25:1:30:3 | | ssa.rb:26:7:26:10 | elem | | ssa.rb:25:8:25:15 | elements | ssa.rb:25:8:25:15 | elements | | ssa.rb:26:7:26:10 | elem | ssa.rb:26:7:26:10 | elem | @@ -72,13 +72,13 @@ definition | ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo | | ssa.rb:54:3:54:11 | ... = ... | ssa.rb:54:3:54:3 | x | | ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | -| ssa.rb:60:3:60:9 | ... += ... | ssa.rb:59:3:59:3 | x | +| ssa.rb:60:3:60:9 | ... = ... | ssa.rb:59:3:59:3 | x | | ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a | | ssa.rb:65:3:65:15 | ... = ... | ssa.rb:65:3:65:10 | captured | | ssa.rb:66:3:70:5 | call to times | ssa.rb:65:3:65:10 | captured | | ssa.rb:66:11:70:5 | | ssa.rb:65:3:65:10 | captured | | ssa.rb:66:15:66:15 | a | ssa.rb:66:15:66:15 | a | -| ssa.rb:69:5:69:17 | ... += ... | ssa.rb:65:3:65:10 | captured | +| ssa.rb:69:5:69:17 | ... = ... | ssa.rb:65:3:65:10 | captured | | ssa.rb:75:3:75:14 | ... = ... | ssa.rb:75:3:75:10 | captured | | ssa.rb:76:7:78:5 | | ssa.rb:75:3:75:10 | captured | | ssa.rb:82:3:82:14 | ... = ... | ssa.rb:82:3:82:10 | captured | @@ -124,8 +124,8 @@ read | scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | | scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a | | scopes.rb:9:9:18:3 | | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a | -| scopes.rb:9:9:18:3 | | scopes.rb:7:1:7:1 | a | scopes.rb:11:4:11:4 | a | -| scopes.rb:11:4:11:9 | ... += ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | +| scopes.rb:9:9:18:3 | | scopes.rb:7:1:7:1 | a | scopes.rb:11:4:11:9 | a | +| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c | @@ -145,7 +145,7 @@ read | ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:12:10:12:10 | i | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:19:9:19:9 | x | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:20:10:20:10 | x | -| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:5 | x | +| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:10 | x | | ssa.rb:25:8:25:15 | elements | ssa.rb:25:8:25:15 | elements | ssa.rb:26:15:26:22 | elements | | ssa.rb:26:7:26:10 | elem | ssa.rb:26:7:26:10 | elem | ssa.rb:27:10:27:13 | elem | | ssa.rb:26:12:26:22 | phi | ssa.rb:26:7:26:10 | elem | ssa.rb:29:8:29:11 | elem | @@ -156,12 +156,12 @@ read | ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:50:8:50:8 | y | | ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo | ssa.rb:54:7:54:9 | foo | | ssa.rb:54:3:54:11 | ... = ... | ssa.rb:54:3:54:3 | x | ssa.rb:55:8:55:8 | x | -| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:3 | x | -| ssa.rb:60:3:60:9 | ... += ... | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | +| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:9 | x | +| ssa.rb:60:3:60:9 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | | ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a | ssa.rb:66:3:66:3 | a | | ssa.rb:66:3:70:5 | call to times | ssa.rb:65:3:65:10 | captured | ssa.rb:71:8:71:15 | captured | | ssa.rb:66:11:70:5 | | ssa.rb:65:3:65:10 | captured | ssa.rb:68:10:68:17 | captured | -| ssa.rb:66:11:70:5 | | ssa.rb:65:3:65:10 | captured | ssa.rb:69:5:69:12 | captured | +| ssa.rb:66:11:70:5 | | ssa.rb:65:3:65:10 | captured | ssa.rb:69:5:69:17 | captured | | ssa.rb:66:15:66:15 | a | ssa.rb:66:15:66:15 | a | ssa.rb:67:10:67:10 | a | | ssa.rb:76:7:78:5 | | ssa.rb:75:3:75:10 | captured | ssa.rb:77:15:77:22 | captured | | ssa.rb:84:10:86:8 | | ssa.rb:82:3:82:10 | captured | ssa.rb:85:15:85:22 | captured | @@ -204,7 +204,7 @@ firstRead | scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | | scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a | | scopes.rb:9:9:18:3 | | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a | -| scopes.rb:11:4:11:9 | ... += ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | +| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c | @@ -226,8 +226,8 @@ firstRead | ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:50:8:50:8 | y | | ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo | ssa.rb:54:7:54:9 | foo | | ssa.rb:54:3:54:11 | ... = ... | ssa.rb:54:3:54:3 | x | ssa.rb:55:8:55:8 | x | -| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:3 | x | -| ssa.rb:60:3:60:9 | ... += ... | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | +| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:9 | x | +| ssa.rb:60:3:60:9 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | | ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a | ssa.rb:66:3:66:3 | a | | ssa.rb:66:3:70:5 | call to times | ssa.rb:65:3:65:10 | captured | ssa.rb:71:8:71:15 | captured | | ssa.rb:66:11:70:5 | | ssa.rb:65:3:65:10 | captured | ssa.rb:68:10:68:17 | captured | @@ -272,8 +272,8 @@ lastRead | parameters.rb:55:4:55:9 | phi | parameters.rb:53:1:53:1 | x | parameters.rb:55:9:55:9 | x | | scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | | scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a | -| scopes.rb:9:9:18:3 | | scopes.rb:7:1:7:1 | a | scopes.rb:11:4:11:4 | a | -| scopes.rb:11:4:11:9 | ... += ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | +| scopes.rb:9:9:18:3 | | scopes.rb:7:1:7:1 | a | scopes.rb:11:4:11:9 | a | +| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b | | scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c | @@ -285,7 +285,7 @@ lastRead | ssa.rb:6:5:6:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:8:10:8:10 | i | | ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:12:10:12:10 | i | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:19:9:19:9 | x | -| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:5 | x | +| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:10 | x | | ssa.rb:25:8:25:15 | elements | ssa.rb:25:8:25:15 | elements | ssa.rb:26:15:26:22 | elements | | ssa.rb:26:7:26:10 | elem | ssa.rb:26:7:26:10 | elem | ssa.rb:27:10:27:13 | elem | | ssa.rb:26:12:26:22 | phi | ssa.rb:26:7:26:10 | elem | ssa.rb:29:8:29:11 | elem | @@ -296,11 +296,11 @@ lastRead | ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:50:8:50:8 | y | | ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo | ssa.rb:54:7:54:9 | foo | | ssa.rb:54:3:54:11 | ... = ... | ssa.rb:54:3:54:3 | x | ssa.rb:55:8:55:8 | x | -| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:3 | x | -| ssa.rb:60:3:60:9 | ... += ... | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | +| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:9 | x | +| ssa.rb:60:3:60:9 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | | ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a | ssa.rb:66:3:66:3 | a | | ssa.rb:66:3:70:5 | call to times | ssa.rb:65:3:65:10 | captured | ssa.rb:71:8:71:15 | captured | -| ssa.rb:66:11:70:5 | | ssa.rb:65:3:65:10 | captured | ssa.rb:69:5:69:12 | captured | +| ssa.rb:66:11:70:5 | | ssa.rb:65:3:65:10 | captured | ssa.rb:69:5:69:17 | captured | | ssa.rb:66:15:66:15 | a | ssa.rb:66:15:66:15 | a | ssa.rb:67:10:67:10 | a | | ssa.rb:76:7:78:5 | | ssa.rb:75:3:75:10 | captured | ssa.rb:77:15:77:22 | captured | | ssa.rb:84:10:86:8 | | ssa.rb:82:3:82:10 | captured | ssa.rb:85:15:85:22 | captured | @@ -308,7 +308,7 @@ adjacentReads | nested_scopes.rb:13:11:13:15 | ... = ... | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:14:16:14:16 | a | nested_scopes.rb:15:11:15:11 | a | | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas | parameters.rb:11:14:11:19 | pizzas | | parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:40:25:43 | name | parameters.rb:26:8:26:11 | name | -| scopes.rb:9:9:18:3 | | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a | scopes.rb:11:4:11:4 | a | +| scopes.rb:9:9:18:3 | | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a | scopes.rb:11:4:11:9 | a | | scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x | scopes.rb:31:10:31:10 | x | | scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:31:10:31:10 | x | scopes.rb:34:7:34:7 | x | | scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:34:7:34:7 | x | scopes.rb:34:14:34:14 | x | @@ -317,8 +317,8 @@ adjacentReads | ssa.rb:6:5:6:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:7:10:7:10 | i | ssa.rb:8:10:8:10 | i | | ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:11:10:11:10 | i | ssa.rb:12:10:12:10 | i | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:19:9:19:9 | x | ssa.rb:20:10:20:10 | x | -| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:20:10:20:10 | x | ssa.rb:21:5:21:5 | x | -| ssa.rb:66:11:70:5 | | ssa.rb:65:3:65:10 | captured | ssa.rb:68:10:68:17 | captured | ssa.rb:69:5:69:12 | captured | +| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:20:10:20:10 | x | ssa.rb:21:5:21:10 | x | +| ssa.rb:66:11:70:5 | | ssa.rb:65:3:65:10 | captured | ssa.rb:68:10:68:17 | captured | ssa.rb:69:5:69:17 | captured | phi | parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | | | parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:20 | ... = ... | @@ -329,7 +329,7 @@ phi | ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | ssa.rb:6:5:6:9 | ... = ... | | ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | ssa.rb:10:5:10:9 | ... = ... | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:18:8:18:8 | x | -| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:10 | ... -= ... | +| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:10 | ... = ... | | ssa.rb:26:12:26:22 | phi | ssa.rb:26:7:26:10 | elem | ssa.rb:25:1:30:3 | | | ssa.rb:26:12:26:22 | phi | ssa.rb:26:7:26:10 | elem | ssa.rb:26:7:26:10 | elem | | ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | ssa.rb:44:1:47:3 | | diff --git a/ql/test/library-tests/variables/varaccess.expected b/ql/test/library-tests/variables/varaccess.expected index 55ce10e6324..f611922dfbc 100644 --- a/ql/test/library-tests/variables/varaccess.expected +++ b/ql/test/library-tests/variables/varaccess.expected @@ -103,6 +103,7 @@ variableAccess | scopes.rb:9:14:9:14 | x | scopes.rb:9:14:9:14 | x | scopes.rb:9:9:18:3 | do ... end | | scopes.rb:10:9:10:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:40:1 | scopes.rb | | scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:40:1 | scopes.rb | +| scopes.rb:11:4:11:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:40:1 | scopes.rb | | scopes.rb:12:9:12:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:40:1 | scopes.rb | | scopes.rb:13:4:13:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:40:1 | scopes.rb | | scopes.rb:13:7:13:7 | b | scopes.rb:13:7:13:7 | b | scopes.rb:9:9:18:3 | do ... end | @@ -139,6 +140,7 @@ variableAccess | ssa.rb:19:9:19:9 | x | ssa.rb:18:8:18:8 | x | ssa.rb:18:1:23:3 | m1 | | ssa.rb:20:10:20:10 | x | ssa.rb:18:8:18:8 | x | ssa.rb:18:1:23:3 | m1 | | ssa.rb:21:5:21:5 | x | ssa.rb:18:8:18:8 | x | ssa.rb:18:1:23:3 | m1 | +| ssa.rb:21:5:21:10 | x | ssa.rb:18:8:18:8 | x | ssa.rb:18:1:23:3 | m1 | | ssa.rb:25:8:25:15 | elements | ssa.rb:25:8:25:15 | elements | ssa.rb:25:1:30:3 | m2 | | ssa.rb:26:7:26:10 | elem | ssa.rb:26:7:26:10 | elem | ssa.rb:25:1:30:3 | m2 | | ssa.rb:26:15:26:22 | elements | ssa.rb:25:8:25:15 | elements | ssa.rb:25:1:30:3 | m2 | @@ -161,6 +163,7 @@ variableAccess | ssa.rb:55:8:55:8 | x | ssa.rb:54:3:54:3 | x | ssa.rb:53:1:56:3 | m7 | | ssa.rb:59:3:59:3 | x | ssa.rb:59:3:59:3 | x | ssa.rb:58:1:62:3 | m8 | | ssa.rb:60:3:60:3 | x | ssa.rb:59:3:59:3 | x | ssa.rb:58:1:62:3 | m8 | +| ssa.rb:60:3:60:9 | x | ssa.rb:59:3:59:3 | x | ssa.rb:58:1:62:3 | m8 | | ssa.rb:61:8:61:8 | x | ssa.rb:59:3:59:3 | x | ssa.rb:58:1:62:3 | m8 | | ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a | ssa.rb:64:1:72:3 | m9 | | ssa.rb:65:3:65:10 | captured | ssa.rb:65:3:65:10 | captured | ssa.rb:64:1:72:3 | m9 | @@ -169,6 +172,7 @@ variableAccess | ssa.rb:67:10:67:10 | a | ssa.rb:66:15:66:15 | a | ssa.rb:66:11:70:5 | do ... end | | ssa.rb:68:10:68:17 | captured | ssa.rb:65:3:65:10 | captured | ssa.rb:64:1:72:3 | m9 | | ssa.rb:69:5:69:12 | captured | ssa.rb:65:3:65:10 | captured | ssa.rb:64:1:72:3 | m9 | +| ssa.rb:69:5:69:17 | captured | ssa.rb:65:3:65:10 | captured | ssa.rb:64:1:72:3 | m9 | | ssa.rb:71:8:71:15 | captured | ssa.rb:65:3:65:10 | captured | ssa.rb:64:1:72:3 | m9 | | ssa.rb:75:3:75:10 | captured | ssa.rb:75:3:75:10 | captured | ssa.rb:74:1:79:3 | m10 | | ssa.rb:77:15:77:22 | captured | ssa.rb:75:3:75:10 | captured | ssa.rb:74:1:79:3 | m10 | @@ -205,6 +209,7 @@ explicitWrite | scopes.rb:4:4:4:4 | a | scopes.rb:4:4:4:8 | ... = ... | | scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:5 | ... = ... | | scopes.rb:11:4:11:4 | a | scopes.rb:11:4:11:9 | ... += ... | +| scopes.rb:11:4:11:4 | a | scopes.rb:11:4:11:9 | ... = ... | | scopes.rb:13:4:13:4 | a | scopes.rb:13:4:13:32 | ... = ... | | scopes.rb:13:7:13:7 | b | scopes.rb:13:4:13:32 | ... = ... | | scopes.rb:13:11:13:11 | c | scopes.rb:13:4:13:32 | ... = ... | @@ -220,14 +225,17 @@ explicitWrite | ssa.rb:6:5:6:5 | i | ssa.rb:6:5:6:9 | ... = ... | | ssa.rb:10:5:10:5 | i | ssa.rb:10:5:10:9 | ... = ... | | ssa.rb:21:5:21:5 | x | ssa.rb:21:5:21:10 | ... -= ... | +| ssa.rb:21:5:21:5 | x | ssa.rb:21:5:21:10 | ... = ... | | ssa.rb:40:3:40:4 | m3 | ssa.rb:40:3:40:9 | ... = ... | | ssa.rb:45:3:45:3 | x | ssa.rb:45:3:45:7 | ... = ... | | ssa.rb:49:14:49:14 | y | ssa.rb:49:14:49:19 | ... = ... | | ssa.rb:54:3:54:3 | x | ssa.rb:54:3:54:11 | ... = ... | | ssa.rb:59:3:59:3 | x | ssa.rb:59:3:59:8 | ... = ... | | ssa.rb:60:3:60:3 | x | ssa.rb:60:3:60:9 | ... += ... | +| ssa.rb:60:3:60:3 | x | ssa.rb:60:3:60:9 | ... = ... | | ssa.rb:65:3:65:10 | captured | ssa.rb:65:3:65:15 | ... = ... | | ssa.rb:69:5:69:12 | captured | ssa.rb:69:5:69:17 | ... += ... | +| ssa.rb:69:5:69:12 | captured | ssa.rb:69:5:69:17 | ... = ... | | ssa.rb:75:3:75:10 | captured | ssa.rb:75:3:75:14 | ... = ... | | ssa.rb:82:3:82:10 | captured | ssa.rb:82:3:82:14 | ... = ... | implicitWrite @@ -316,7 +324,7 @@ readAccess | scopes.rb:5:9:5:9 | a | | scopes.rb:8:6:8:6 | a | | scopes.rb:10:9:10:9 | a | -| scopes.rb:11:4:11:4 | a | +| scopes.rb:11:4:11:9 | a | | scopes.rb:12:9:12:9 | a | | scopes.rb:14:9:14:9 | a | | scopes.rb:15:9:15:9 | b | @@ -338,7 +346,7 @@ readAccess | ssa.rb:15:8:15:8 | i | | ssa.rb:19:9:19:9 | x | | ssa.rb:20:10:20:10 | x | -| ssa.rb:21:5:21:5 | x | +| ssa.rb:21:5:21:10 | x | | ssa.rb:26:15:26:22 | elements | | ssa.rb:27:10:27:13 | elem | | ssa.rb:29:8:29:11 | elem | @@ -349,12 +357,12 @@ readAccess | ssa.rb:50:8:50:8 | y | | ssa.rb:54:7:54:9 | foo | | ssa.rb:55:8:55:8 | x | -| ssa.rb:60:3:60:3 | x | +| ssa.rb:60:3:60:9 | x | | ssa.rb:61:8:61:8 | x | | ssa.rb:66:3:66:3 | a | | ssa.rb:67:10:67:10 | a | | ssa.rb:68:10:68:17 | captured | -| ssa.rb:69:5:69:12 | captured | +| ssa.rb:69:5:69:17 | captured | | ssa.rb:71:8:71:15 | captured | | ssa.rb:77:15:77:22 | captured | | ssa.rb:85:15:85:22 | captured | From b434d42d05d57bc3f63e3cd0fcdfc06d8728aca2 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 17 May 2021 13:39:44 +0200 Subject: [PATCH 3/4] Rename `ParenthesizedExprSynth` to `StmtSequenceSynth` --- ql/src/codeql_ruby/ast/Expr.qll | 24 +++++++++---------- ql/src/codeql_ruby/ast/internal/AST.qll | 18 ++++++-------- ql/src/codeql_ruby/ast/internal/Synthesis.qll | 2 +- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/ql/src/codeql_ruby/ast/Expr.qll b/ql/src/codeql_ruby/ast/Expr.qll index 17b52b97268..2eccc897ed7 100644 --- a/ql/src/codeql_ruby/ast/Expr.qll +++ b/ql/src/codeql_ruby/ast/Expr.qll @@ -79,6 +79,12 @@ class StmtSequence extends Expr, TStmtSequence { override AstNode getAChild(string pred) { pred = "getStmt" and result = this.getStmt(_) } } +private class StmtSequenceSynth extends StmtSequence, TStmtSequenceSynth { + final override Stmt getStmt(int n) { synthChild(this, n, result) } + + final override string toString() { result = "..." } +} + private class Then extends StmtSequence, TThen { private Generated::Then g; @@ -206,23 +212,17 @@ class BodyStmt extends StmtSequence, TBodyStmt { * ``` */ class ParenthesizedExpr extends StmtSequence, TParenthesizedExpr { + private Generated::ParenthesizedStatements g; + + ParenthesizedExpr() { this = TParenthesizedExpr(g) } + + final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) } + final override string getAPrimaryQlClass() { result = "ParenthesizedExpr" } final override string toString() { result = "( ... )" } } -private class ParenthesizedExprReal extends ParenthesizedExpr, TParenthesizedExprReal { - private Generated::ParenthesizedStatements g; - - ParenthesizedExprReal() { this = TParenthesizedExprReal(g) } - - final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) } -} - -private class ParenthesizedExprSynth extends ParenthesizedExpr, TParenthesizedExprSynth { - final override Stmt getStmt(int n) { synthChild(this, n, result) } -} - /** * A pair expression. For example, in a hash: * ```rb diff --git a/ql/src/codeql_ruby/ast/internal/AST.qll b/ql/src/codeql_ruby/ast/internal/AST.qll index 9dd3c35058e..7af573dad0d 100644 --- a/ql/src/codeql_ruby/ast/internal/AST.qll +++ b/ql/src/codeql_ruby/ast/internal/AST.qll @@ -188,10 +188,7 @@ private module Cached { TNotExpr(Generated::Unary g) { g instanceof @unary_bang or g instanceof @unary_not } or TOptionalParameter(Generated::OptionalParameter g) or TPair(Generated::Pair g) or - TParenthesizedExprReal(Generated::ParenthesizedStatements g) or - TParenthesizedExprSynth(AST::AstNode parent, int i) { - mkSynthChild(ParenthesizedExprKind(), parent, i) - } or + TParenthesizedExpr(Generated::ParenthesizedStatements g) or TRShiftExprReal(Generated::Binary g) { g instanceof @binary_ranglerangle } or TRShiftExprSynth(AST::AstNode parent, int i) { mkSynthChild(RShiftExprKind(), parent, i) } or TRangeLiteral(Generated::Range g) or @@ -231,6 +228,7 @@ private module Cached { TSpaceshipExpr(Generated::Binary g) { g instanceof @binary_langleequalrangle } or TSplatArgument(Generated::SplatArgument g) or TSplatParameter(Generated::SplatParameter g) or + TStmtSequenceSynth(AST::AstNode parent, int i) { mkSynthChild(StmtSequenceKind(), parent, i) } or TStringArrayLiteral(Generated::StringArray g) or TStringConcatenation(Generated::ChainedString g) or TStringEscapeSequenceComponent(Generated::EscapeSequence g) or @@ -369,7 +367,7 @@ private module Cached { n = TNotExpr(result) or n = TOptionalParameter(result) or n = TPair(result) or - n = TParenthesizedExprReal(result) or + n = TParenthesizedExpr(result) or n = TRShiftExprReal(result) or n = TRangeLiteral(result) or n = TRationalLiteral(result) or @@ -484,15 +482,15 @@ private module Cached { kind = MulExprKind() and result = TMulExprSynth(parent, i) or - kind = ParenthesizedExprKind() and - result = TParenthesizedExprSynth(parent, i) - or kind = RShiftExprKind() and result = TRShiftExprSynth(parent, i) or kind = SelfKind() and result = TSelfSynth(parent, i) or + kind = StmtSequenceKind() and + result = TStmtSequenceSynth(parent, i) + or kind = SubExprKind() and result = TSubExprSynth(parent, i) ) @@ -560,9 +558,7 @@ class TExpr = class TStmtSequence = TBeginBlock or TEndBlock or TThen or TElse or TDo or TEnsure or TStringInterpolationComponent or - TBlock or TBodyStmt or TParenthesizedExpr; - -class TParenthesizedExpr = TParenthesizedExprReal or TParenthesizedExprSynth; + TBlock or TBodyStmt or TParenthesizedExpr or TStmtSequenceSynth; class TBodyStmt = TBeginExpr or TModuleBase or TMethod or TLambda or TDoBlock or TSingletonMethod; diff --git a/ql/src/codeql_ruby/ast/internal/Synthesis.qll b/ql/src/codeql_ruby/ast/internal/Synthesis.qll index 6cdca0db8e8..521bd3d430a 100644 --- a/ql/src/codeql_ruby/ast/internal/Synthesis.qll +++ b/ql/src/codeql_ruby/ast/internal/Synthesis.qll @@ -25,7 +25,7 @@ newtype SynthKind = LogicalOrExprKind() or ModuloExprKind() or MulExprKind() or - ParenthesizedExprKind() or + StmtSequenceKind() or RShiftExprKind() or SelfKind() or SubExprKind() From 25f226e9dcde46757bccdb732318a03f8e353fd0 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 17 May 2021 15:02:40 +0200 Subject: [PATCH 4/4] Add comment to `getVariableReal` --- ql/src/codeql_ruby/ast/internal/Variable.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ql/src/codeql_ruby/ast/internal/Variable.qll b/ql/src/codeql_ruby/ast/internal/Variable.qll index 456286f20a2..21becb15cce 100644 --- a/ql/src/codeql_ruby/ast/internal/Variable.qll +++ b/ql/src/codeql_ruby/ast/internal/Variable.qll @@ -508,6 +508,11 @@ class TVariableAccessReal = TClassVariableAccess; abstract class VariableAccessReal extends VariableAccess, TVariableAccessReal { + /** + * Same as `getVariable()`, but restricted to non-synthesized variable accesses. + * + * The sole purpose of this predicate is to make AST synthesis monotonic. + */ abstract VariableReal getVariableReal(); }