From 29a20550f6e3f647096f7f983239585a915f2478 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 17 Apr 2023 08:40:58 +0200 Subject: [PATCH 1/6] Ruby: use MkUse/MkDef for successors, use/def for predecessors --- ruby/ql/lib/codeql/ruby/ApiGraphs.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll index d46859654c5..846382c2397 100644 --- a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll +++ b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll @@ -813,20 +813,20 @@ module API { useRoot(lbl, ref) or exists(DataFlow::Node node, DataFlow::Node src | - pred = MkUse(src) and + use(pred, src) and trackUseNode(src).flowsTo(node) and useStep(lbl, node, ref) ) or exists(DataFlow::Node callback | - pred = MkDef(callback) and + def(pred, callback) and parameterStep(lbl, trackDefNode(callback), ref) ) ) or exists(DataFlow::Node predNode, DataFlow::Node succNode | def(pred, predNode) and - def(succ, succNode) and + succ = MkDef(succNode) and defStep(lbl, trackDefNode(predNode), succNode) ) or @@ -844,7 +844,7 @@ module API { exists(DataFlow::CallNode call | // from receiver to method call node exists(DataFlow::Node receiver | - pred = MkUse(receiver) and + use(pred, receiver) and useNodeReachesReceiver(receiver, call) and lbl = Label::method(call.getMethodName()) and succ = MkMethodAccessNode(call) From 7332cec9a55c1a0f7fd6b7aa6c8f3678cbda0127 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 17 Apr 2023 09:15:34 +0200 Subject: [PATCH 2/6] Ruby: fix missing 'self' parameters in ModuleNode.getAnImmediateReferenc --- ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll index 418e3f621d2..9d668e0b300 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll @@ -890,6 +890,9 @@ class ModuleNode instanceof Module { /** Gets a constant or `self` variable that refers to this module. */ LocalSourceNode getAnImmediateReference() { result.asExpr().getExpr() = super.getAnImmediateReference() + or + // Include 'self' parameters; these are not expressions and so not found by the case above + result = this.getAnOwnModuleSelf() } /** From 8363171f1f10688db519464dadac9440e032ef4a Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 17 Apr 2023 09:27:22 +0200 Subject: [PATCH 3/6] Ruby: Add MkModuleObject as API node for a module/class --- ruby/ql/lib/codeql/ruby/ApiGraphs.qll | 34 +++++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll index 846382c2397..424363924a4 100644 --- a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll +++ b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll @@ -601,7 +601,9 @@ module API { /** A use of an API member at the node `nd`. */ MkUse(DataFlow::Node nd) { isUse(nd) } or /** A value that escapes into an external library at the node `nd` */ - MkDef(DataFlow::Node nd) { isDef(nd) } + MkDef(DataFlow::Node nd) { isDef(nd) } or + /** A module object seen as a use node. */ + MkModuleObject(DataFlow::ModuleNode mod) private string resolveTopLevel(ConstantReadAccess read) { result = read.getModule().getQualifiedName() and @@ -684,7 +686,14 @@ module API { * Holds if `ref` is a use of node `nd`. */ cached - predicate use(TApiNode nd, DataFlow::Node ref) { nd = MkUse(ref) } + predicate use(TApiNode nd, DataFlow::Node ref) { + nd = MkUse(ref) + or + exists(DataFlow::ModuleNode mod | + nd = MkModuleObject(mod) and + ref = mod.getAnImmediateReference() + ) + } /** * Holds if `rhs` is a RHS of node `nd`. @@ -802,6 +811,14 @@ module API { trackUseNode(use).flowsTo(call.getReceiver()) } + /** + * Holds if `superclass` is the superclass of `mod`. + */ + pragma[nomagic] + private predicate superclassNode(DataFlow::ModuleNode mod, DataFlow::Node superclass) { + superclass.asExpr().getExpr() = mod.getADeclaration().(ClassDeclaration).getSuperclassExpr() + } + /** * Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`. */ @@ -830,14 +847,11 @@ module API { defStep(lbl, trackDefNode(predNode), succNode) ) or - // `pred` is a use of class A - // `succ` is a use of class B - // there exists a class declaration B < A - exists(ClassDeclaration c, DataFlow::Node a, DataFlow::Node b | - use(pred, a) and - use(succ, b) and - b.asExpr().getExpr().(ConstantReadAccess).getAQualifiedName() = c.getAQualifiedName() and - pragma[only_bind_into](c).getSuperclassExpr() = a.asExpr().getExpr() and + exists(DataFlow::Node predNode, DataFlow::Node superclassNode, DataFlow::ModuleNode mod | + use(pred, predNode) and + trackUseNode(predNode).flowsTo(superclassNode) and + superclassNode(mod, superclassNode) and + succ = MkModuleObject(mod) and lbl = Label::subclass() ) or From 8c0c335daf3afe74917d1c6f0d3372518ff978bc Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 17 Apr 2023 09:50:23 +0200 Subject: [PATCH 4/6] Ruby: update test output --- .../dataflow/helpers/dataflow.expected | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ruby/ql/test/library-tests/dataflow/helpers/dataflow.expected b/ruby/ql/test/library-tests/dataflow/helpers/dataflow.expected index 299a840e94c..fb2043d9759 100644 --- a/ruby/ql/test/library-tests/dataflow/helpers/dataflow.expected +++ b/ruby/ql/test/library-tests/dataflow/helpers/dataflow.expected @@ -127,11 +127,28 @@ getModuleLevelSelf getAnImmediateReference | file://:0:0:0:0 | Array | tst.rb:59:15:59:21 | Array | | file://:0:0:0:0 | Hash | tst.rb:60:14:60:45 | Hash | +| tst.rb:1:1:6:3 | C1 | tst.rb:1:1:6:3 | self (C1) | | tst.rb:1:1:6:3 | C1 | tst.rb:8:12:8:13 | C1 | +| tst.rb:8:1:11:3 | C2 | tst.rb:8:1:11:3 | self (C2) | | tst.rb:8:1:11:3 | C2 | tst.rb:27:12:27:13 | C2 | +| tst.rb:13:1:18:3 | Mixin | tst.rb:13:1:18:3 | self (Mixin) | +| tst.rb:13:1:18:3 | Mixin | tst.rb:16:5:17:7 | self in m1s | | tst.rb:13:1:18:3 | Mixin | tst.rb:28:13:28:17 | Mixin | +| tst.rb:20:1:25:3 | Mixin2 | tst.rb:20:1:25:3 | self (Mixin2) | +| tst.rb:20:1:25:3 | Mixin2 | tst.rb:23:5:24:7 | self in m2s | | tst.rb:20:1:25:3 | Mixin2 | tst.rb:29:13:29:18 | Mixin2 | +| tst.rb:27:1:35:3 | C3 | tst.rb:27:1:35:3 | self (C3) | +| tst.rb:27:1:35:3 | C3 | tst.rb:32:9:33:11 | self in c3_self1 | +| tst.rb:27:1:35:3 | C3 | tst.rb:37:1:38:3 | self in c3_self2 | | tst.rb:27:1:35:3 | C3 | tst.rb:37:5:37:6 | C3 | +| tst.rb:40:1:47:3 | N1 | tst.rb:40:1:47:3 | self (N1) | +| tst.rb:41:5:42:7 | N1::XY1 | tst.rb:41:5:42:7 | self (XY1) | +| tst.rb:43:5:46:7 | N1::N2 | tst.rb:43:5:46:7 | self (N2) | +| tst.rb:44:9:45:11 | N1::N2::XY2 | tst.rb:44:9:45:11 | self (XY2) | +| tst.rb:49:1:51:3 | N2 | tst.rb:49:1:51:3 | self (N2) | +| tst.rb:49:1:51:3 | N2 | tst.rb:52:1:55:3 | self (N2) | +| tst.rb:53:5:54:7 | N2::XY3 | tst.rb:53:5:54:7 | self (XY3) | +| tst.rb:57:1:62:3 | Nodes | tst.rb:57:1:62:3 | self (Nodes) | getOwnInstanceMethod | tst.rb:1:1:6:3 | C1 | c1 | tst.rb:2:5:5:7 | c1 | | tst.rb:8:1:11:3 | C2 | c2 | tst.rb:9:5:10:7 | c2 | From e180b7e2ba340ed7949c1a05a1d95c9ce991dde4 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 17 Apr 2023 12:49:35 +0200 Subject: [PATCH 5/6] Ruby: add locations for module object nodes --- ruby/ql/lib/codeql/ruby/ApiGraphs.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll index 424363924a4..b1320d047cc 100644 --- a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll +++ b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll @@ -359,6 +359,11 @@ module API { Location getLocation() { result = this.getInducingNode().getLocation() or + exists(DataFlow::ModuleNode mod | + this = Impl::MkModuleObject(mod) and + result = mod.getLocation() + ) + or // For nodes that do not have a meaningful location, `path` is the empty string and all other // parameters are zero. not exists(this.getInducingNode()) and From 149753c052121485765ff8dd26fde81d37d2913e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Apr 2023 04:03:04 +0000 Subject: [PATCH 6/6] Bump regex from 1.7.3 to 1.8.0 in /ql Bumps [regex](https://github.com/rust-lang/regex) from 1.7.3 to 1.8.0. - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/commits) --- updated-dependencies: - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- ql/Cargo.lock | Bin 31789 -> 31997 bytes ql/buramu/Cargo.toml | 2 +- ql/extractor/Cargo.toml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ql/Cargo.lock b/ql/Cargo.lock index e071c5e71b402f5087cb30244be31f313bbcfd95..3ba709a5edefa547ccf2d5e70e3207440d8b85ec 100644 GIT binary patch delta 282 zcmW;GJxYT?6op|1i7r4Sl1j9&3-@Pc?j0=N1UuI->kx#jAdS7Na0jBG z;D^O2p6a|WU+(wYz3$u*E@8lIyNY5JwDv?$8M74u1LRg~$6}Q;V+yUuOr&0X_o1Vq z4~3&?13wP4v;B|T-3|A&yUjIL3n?2yl+0Gbv>vKzg}@ShPYjlrO2;PH*sKFno#@5F za5wYud4GL;0ZW+zpU)RV9^OwT#wDeHU#{QA)q3G%Y)`kV5;dx(sFF$!Oyt#=L(GlA6cOy;_VIn+ z?DS&ihLyZBmB`1@VHpBRR6vO^IROyB6Che^ytGkA#XS(|p5Bu7(F8~&T^obp23*LO zV%&XLvnos_GnD&<^^lOH7b>9(1R^O*GA3??Qmx@0IT~eoD-t+`ku(p41hHRgAwTAm X{M^hk8%%Rm5A%9^|NGWmcQyV1kH