From 1126dc43f4dbb06bdf8d896131e354777d410550 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Wed, 11 Sep 2024 11:16:06 +0200 Subject: [PATCH] Fix control flow tree for function and block expression --- .../rust/controlflow/ControlFlowGraph.qll | 2 +- .../internal/ControlFlowGraphImpl.qll | 18 ++-- .../rust/controlflow/internal/PrintCfg.ql | 9 +- .../library-tests/controlflow/Cfg.expected | 92 +++++++++++++++++++ rust/ql/test/library-tests/controlflow/Cfg.ql | 3 + .../ql/test/library-tests/controlflow/test.rs | 15 ++- 6 files changed, 123 insertions(+), 16 deletions(-) diff --git a/rust/ql/lib/codeql/rust/controlflow/ControlFlowGraph.qll b/rust/ql/lib/codeql/rust/controlflow/ControlFlowGraph.qll index 1934b5ea633a9..e8e6e5f98c9d0 100644 --- a/rust/ql/lib/codeql/rust/controlflow/ControlFlowGraph.qll +++ b/rust/ql/lib/codeql/rust/controlflow/ControlFlowGraph.qll @@ -4,8 +4,8 @@ private import rust private import internal.ControlFlowGraphImpl private import internal.Completion private import internal.SuccessorType -private import codeql.rust.controlflow.BasicBlocks private import internal.Scope as Scope +private import BasicBlocks final class CfgScope = Scope::CfgScope; diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 7e866a0d36a62..1370362bf0f0f 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -63,18 +63,17 @@ module CfgImpl = Make; import CfgImpl -class FunctionTree extends LeafTree instanceof Function { } +class FunctionTree extends StandardPostOrderTree instanceof Function { + override ControlFlowTree getChildNode(int i) { i = 0 and result = super.getBody() } +} class BlockExprTree extends StandardPostOrderTree instanceof BlockExpr { override ControlFlowTree getChildNode(int i) { result = super.getStatement(i) or - exists(int last | - last + 1 = i and - exists(super.getStatement(last)) and - not exists(super.getStatement(last + 1)) and - result = super.getTail() - ) + not exists(super.getStatement(i)) and + (exists(super.getStatement(i - 1)) or i = 0) and + result = super.getTail() } } @@ -123,3 +122,8 @@ class LetExprTree extends StandardPostOrderTree instanceof LetExpr { } class LiteralExprTree extends LeafTree instanceof LiteralExpr { } + +class PathExprTree extends LeafTree instanceof PathExpr { } + +// A leaf tree for unimplemented nodes in the AST. +class UnimplementedTree extends LeafTree instanceof Unimplemented { } diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/PrintCfg.ql b/rust/ql/lib/codeql/rust/controlflow/internal/PrintCfg.ql index a5b76afb7580e..d4db94ca22aee 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/PrintCfg.ql +++ b/rust/ql/lib/codeql/rust/controlflow/internal/PrintCfg.ql @@ -8,9 +8,8 @@ */ private import codeql.rust.elements.File +private import codeql.rust.controlflow.internal.ControlFlowGraphImpl private import codeql.rust.controlflow.ControlFlowGraph -private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as Impl -private import codeql.rust.controlflow.internal.ControlFlowGraphImplSpecific /** * Gets the source file to generate a CFG from. @@ -33,7 +32,7 @@ external int selectedSourceColumn(); private predicate selectedSourceColumnAlias = selectedSourceColumn/0; -private module ViewCfgQueryInput implements Impl::ViewCfgQueryInputSig { +private module ViewCfgQueryInput implements ViewCfgQueryInputSig { predicate selectedSourceFile = selectedSourceFileAlias/0; predicate selectedSourceLine = selectedSourceLineAlias/0; @@ -41,11 +40,11 @@ private module ViewCfgQueryInput implements Impl::ViewCfgQueryInputSig { predicate selectedSourceColumn = selectedSourceColumnAlias/0; predicate cfgScopeSpan( - CfgInput::CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn + CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn ) { file = scope.getFile() and scope.getLocation().hasLocationInfo(_, startLine, startColumn, endLine, endColumn) } } -import Impl::ViewCfgQuery +import ViewCfgQuery diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index e69de29bb2d1d..57cbfe8c00113 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -0,0 +1,92 @@ +nodes +| test.rs:1:1:7:1 | enter main | semmle.order | 1 | +| test.rs:1:1:7:1 | exit main | semmle.order | 2 | +| test.rs:1:1:7:1 | exit main (normal) | semmle.order | 3 | +| test.rs:1:1:7:1 | main | semmle.order | 4 | +| test.rs:1:18:7:1 | BlockExpr | semmle.order | 5 | +| test.rs:2:5:6:5 | IfExpr | semmle.order | 6 | +| test.rs:2:8:2:12 | LiteralExpr | semmle.order | 7 | +| test.rs:2:8:2:21 | BinaryOpExpr | semmle.order | 8 | +| test.rs:2:17:2:21 | LiteralExpr | semmle.order | 9 | +| test.rs:2:23:4:5 | BlockExpr | semmle.order | 10 | +| test.rs:3:9:3:20 | CallExpr | semmle.order | 11 | +| test.rs:3:19:3:19 | LiteralExpr | semmle.order | 12 | +| test.rs:4:12:6:5 | BlockExpr | semmle.order | 13 | +| test.rs:5:9:5:20 | CallExpr | semmle.order | 14 | +| test.rs:5:19:5:19 | LiteralExpr | semmle.order | 15 | +| test.rs:9:1:16:1 | decrement | semmle.order | 16 | +| test.rs:9:1:16:1 | enter decrement | semmle.order | 17 | +| test.rs:9:1:16:1 | exit decrement | semmle.order | 18 | +| test.rs:9:1:16:1 | exit decrement (normal) | semmle.order | 19 | +| test.rs:9:29:16:1 | BlockExpr | semmle.order | 20 | +| test.rs:11:5:15:5 | IfExpr | semmle.order | 21 | +| test.rs:11:8:11:8 | PathExpr | semmle.order | 22 | +| test.rs:11:8:11:13 | BinaryOpExpr | semmle.order | 23 | +| test.rs:11:13:11:13 | LiteralExpr | semmle.order | 24 | +| test.rs:11:15:13:5 | BlockExpr | semmle.order | 25 | +| test.rs:12:9:12:9 | LiteralExpr | semmle.order | 26 | +| test.rs:13:12:15:5 | BlockExpr | semmle.order | 27 | +| test.rs:14:9:14:9 | PathExpr | semmle.order | 28 | +| test.rs:14:9:14:13 | BinaryOpExpr | semmle.order | 29 | +| test.rs:14:13:14:13 | LiteralExpr | semmle.order | 30 | +edges +| test.rs:1:1:7:1 | enter main | test.rs:2:8:2:12 | LiteralExpr | semmle.label | | +| test.rs:1:1:7:1 | enter main | test.rs:2:8:2:12 | LiteralExpr | semmle.order | 1 | +| test.rs:1:1:7:1 | exit main (normal) | test.rs:1:1:7:1 | exit main | semmle.label | | +| test.rs:1:1:7:1 | exit main (normal) | test.rs:1:1:7:1 | exit main | semmle.order | 1 | +| test.rs:1:1:7:1 | main | test.rs:1:1:7:1 | exit main (normal) | semmle.label | | +| test.rs:1:1:7:1 | main | test.rs:1:1:7:1 | exit main (normal) | semmle.order | 1 | +| test.rs:1:18:7:1 | BlockExpr | test.rs:1:1:7:1 | main | semmle.label | | +| test.rs:1:18:7:1 | BlockExpr | test.rs:1:1:7:1 | main | semmle.order | 1 | +| test.rs:2:5:6:5 | IfExpr | test.rs:1:18:7:1 | BlockExpr | semmle.label | | +| test.rs:2:5:6:5 | IfExpr | test.rs:1:18:7:1 | BlockExpr | semmle.order | 1 | +| test.rs:2:8:2:12 | LiteralExpr | test.rs:2:17:2:21 | LiteralExpr | semmle.label | | +| test.rs:2:8:2:12 | LiteralExpr | test.rs:2:17:2:21 | LiteralExpr | semmle.order | 1 | +| test.rs:2:8:2:21 | BinaryOpExpr | test.rs:3:19:3:19 | LiteralExpr | semmle.label | true | +| test.rs:2:8:2:21 | BinaryOpExpr | test.rs:3:19:3:19 | LiteralExpr | semmle.order | 1 | +| test.rs:2:8:2:21 | BinaryOpExpr | test.rs:5:19:5:19 | LiteralExpr | semmle.label | false | +| test.rs:2:8:2:21 | BinaryOpExpr | test.rs:5:19:5:19 | LiteralExpr | semmle.order | 2 | +| test.rs:2:17:2:21 | LiteralExpr | test.rs:2:8:2:21 | BinaryOpExpr | semmle.label | | +| test.rs:2:17:2:21 | LiteralExpr | test.rs:2:8:2:21 | BinaryOpExpr | semmle.order | 1 | +| test.rs:2:23:4:5 | BlockExpr | test.rs:2:5:6:5 | IfExpr | semmle.label | | +| test.rs:2:23:4:5 | BlockExpr | test.rs:2:5:6:5 | IfExpr | semmle.order | 1 | +| test.rs:3:9:3:20 | CallExpr | test.rs:2:23:4:5 | BlockExpr | semmle.label | | +| test.rs:3:9:3:20 | CallExpr | test.rs:2:23:4:5 | BlockExpr | semmle.order | 1 | +| test.rs:3:19:3:19 | LiteralExpr | test.rs:3:9:3:20 | CallExpr | semmle.label | | +| test.rs:3:19:3:19 | LiteralExpr | test.rs:3:9:3:20 | CallExpr | semmle.order | 1 | +| test.rs:4:12:6:5 | BlockExpr | test.rs:2:5:6:5 | IfExpr | semmle.label | | +| test.rs:4:12:6:5 | BlockExpr | test.rs:2:5:6:5 | IfExpr | semmle.order | 1 | +| test.rs:5:9:5:20 | CallExpr | test.rs:4:12:6:5 | BlockExpr | semmle.label | | +| test.rs:5:9:5:20 | CallExpr | test.rs:4:12:6:5 | BlockExpr | semmle.order | 1 | +| test.rs:5:19:5:19 | LiteralExpr | test.rs:5:9:5:20 | CallExpr | semmle.label | | +| test.rs:5:19:5:19 | LiteralExpr | test.rs:5:9:5:20 | CallExpr | semmle.order | 1 | +| test.rs:9:1:16:1 | decrement | test.rs:9:1:16:1 | exit decrement (normal) | semmle.label | | +| test.rs:9:1:16:1 | decrement | test.rs:9:1:16:1 | exit decrement (normal) | semmle.order | 1 | +| test.rs:9:1:16:1 | enter decrement | test.rs:11:8:11:8 | PathExpr | semmle.label | | +| test.rs:9:1:16:1 | enter decrement | test.rs:11:8:11:8 | PathExpr | semmle.order | 1 | +| test.rs:9:1:16:1 | exit decrement (normal) | test.rs:9:1:16:1 | exit decrement | semmle.label | | +| test.rs:9:1:16:1 | exit decrement (normal) | test.rs:9:1:16:1 | exit decrement | semmle.order | 1 | +| test.rs:9:29:16:1 | BlockExpr | test.rs:9:1:16:1 | decrement | semmle.label | | +| test.rs:9:29:16:1 | BlockExpr | test.rs:9:1:16:1 | decrement | semmle.order | 1 | +| test.rs:11:5:15:5 | IfExpr | test.rs:9:29:16:1 | BlockExpr | semmle.label | | +| test.rs:11:5:15:5 | IfExpr | test.rs:9:29:16:1 | BlockExpr | semmle.order | 1 | +| test.rs:11:8:11:8 | PathExpr | test.rs:11:13:11:13 | LiteralExpr | semmle.label | | +| test.rs:11:8:11:8 | PathExpr | test.rs:11:13:11:13 | LiteralExpr | semmle.order | 1 | +| test.rs:11:8:11:13 | BinaryOpExpr | test.rs:12:9:12:9 | LiteralExpr | semmle.label | true | +| test.rs:11:8:11:13 | BinaryOpExpr | test.rs:12:9:12:9 | LiteralExpr | semmle.order | 1 | +| test.rs:11:8:11:13 | BinaryOpExpr | test.rs:14:9:14:9 | PathExpr | semmle.label | false | +| test.rs:11:8:11:13 | BinaryOpExpr | test.rs:14:9:14:9 | PathExpr | semmle.order | 2 | +| test.rs:11:13:11:13 | LiteralExpr | test.rs:11:8:11:13 | BinaryOpExpr | semmle.label | | +| test.rs:11:13:11:13 | LiteralExpr | test.rs:11:8:11:13 | BinaryOpExpr | semmle.order | 1 | +| test.rs:11:15:13:5 | BlockExpr | test.rs:11:5:15:5 | IfExpr | semmle.label | | +| test.rs:11:15:13:5 | BlockExpr | test.rs:11:5:15:5 | IfExpr | semmle.order | 1 | +| test.rs:12:9:12:9 | LiteralExpr | test.rs:11:15:13:5 | BlockExpr | semmle.label | | +| test.rs:12:9:12:9 | LiteralExpr | test.rs:11:15:13:5 | BlockExpr | semmle.order | 1 | +| test.rs:13:12:15:5 | BlockExpr | test.rs:11:5:15:5 | IfExpr | semmle.label | | +| test.rs:13:12:15:5 | BlockExpr | test.rs:11:5:15:5 | IfExpr | semmle.order | 1 | +| test.rs:14:9:14:9 | PathExpr | test.rs:14:13:14:13 | LiteralExpr | semmle.label | | +| test.rs:14:9:14:9 | PathExpr | test.rs:14:13:14:13 | LiteralExpr | semmle.order | 1 | +| test.rs:14:9:14:13 | BinaryOpExpr | test.rs:13:12:15:5 | BlockExpr | semmle.label | | +| test.rs:14:9:14:13 | BinaryOpExpr | test.rs:13:12:15:5 | BlockExpr | semmle.order | 1 | +| test.rs:14:13:14:13 | LiteralExpr | test.rs:14:9:14:13 | BinaryOpExpr | semmle.label | | +| test.rs:14:13:14:13 | LiteralExpr | test.rs:14:9:14:13 | BinaryOpExpr | semmle.order | 1 | diff --git a/rust/ql/test/library-tests/controlflow/Cfg.ql b/rust/ql/test/library-tests/controlflow/Cfg.ql index e23a3122b370c..7792c6c9cc1ed 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.ql +++ b/rust/ql/test/library-tests/controlflow/Cfg.ql @@ -4,8 +4,11 @@ import rust import codeql.rust.controlflow.ControlFlowGraph +import TestUtils class MyRelevantNode extends CfgNode { + MyRelevantNode() { toBeTested(this.getScope()) } + string getOrderDisambiguation() { result = "" } } diff --git a/rust/ql/test/library-tests/controlflow/test.rs b/rust/ql/test/library-tests/controlflow/test.rs index ecb0ecc98b4b0..f60a227c16c8f 100644 --- a/rust/ql/test/library-tests/controlflow/test.rs +++ b/rust/ql/test/library-tests/controlflow/test.rs @@ -1,7 +1,16 @@ -fn main() { +fn main() -> i64 { if "foo" == "bar" { - println!("foobar"); + decrement(0) } else { - println!("baz") + decrement(5) + } +} + +fn decrement(n: i64) -> i64 { + 12; + if n == 0 { + 0 + } else { + n - 1 } }