Skip to content

Commit

Permalink
Merge pull request #1 from hvitved/rb/data-flow-layer-capture2
Browse files Browse the repository at this point in the history
Ruby: Make sure to always generate SSA definitions for namespace self-variables
  • Loading branch information
asgerf committed Nov 7, 2022
2 parents f991991 + 2737255 commit a213e9e
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 42 deletions.
37 changes: 0 additions & 37 deletions ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,6 @@ private module Cached {
)
} or
TSsaDefinitionNode(Ssa::Definition def) or
TRawNamespaceSelf(Namespace ns) {
not exists(Ssa::SelfDefinition def | def.getSourceVariable() = ns.getModuleSelfVariable())
} or
TNormalParameterNode(Parameter p) {
p instanceof SimpleParameter or
p instanceof OptionalParameter or
Expand Down Expand Up @@ -405,8 +402,6 @@ private module Cached {
or
// Needed for stores in type tracking
TypeTrackerSpecific::storeStepIntoSourceNode(_, n, _)
or
n instanceof TRawNamespaceSelf
}

cached
Expand Down Expand Up @@ -528,38 +523,6 @@ class SsaSelfDefinitionNode extends LocalSourceNode, SsaDefinitionNode {
Scope getSelfScope() { result = self.getDeclaringScope() }
}

/**
* A representative for the created or re-opened class/module in a `Namespace` that does
* not have an SSA definition for `self`.
*/
class RawNamespaceSelf extends NodeImpl, TRawNamespaceSelf {
private Namespace namespace;

RawNamespaceSelf() { this = TRawNamespaceSelf(namespace) }

/** Gets the namespace for which this represents the created or re-opened class/module. */
Namespace getNamespace() { result = namespace }

override CfgScope getCfgScope() { result = namespace.getCfgScope() }

override Location getLocationImpl() { result = namespace.getLocation() }

override string toStringImpl() { result = namespace.toString() }
}

/**
* Gets a representative for the created or re-opened class/module in a `Namespace`.
*
* This is usually the SSA definition for `self`, but if this node does not exist due to lack of liveness,
* it is the `RawNamespaceSelf` node.
*/
LocalSourceNode getNamespaceSelf(Namespace namespace) {
result.(SsaDefinitionNode).getDefinition().(Ssa::SelfDefinition).getSourceVariable() =
namespace.getModuleSelfVariable()
or
result = TRawNamespaceSelf(namespace)
}

/**
* A value returning statement, viewed as a node in a data flow graph.
*
Expand Down
8 changes: 5 additions & 3 deletions ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,11 @@ private module Cached {
LocalSourceNode getConstantAccessNode(ConstantAccess access) {
// Namespaces don't evaluate to the constant being accessed, they return the value of their last statement.
// Use the definition of 'self' in the namespace as the representative in this case.
if access instanceof Namespace
then result = getNamespaceSelf(access)
else result.asExpr().getExpr() = access
result.(SsaDefinitionNode).getDefinition().(Ssa::SelfDefinition).getSourceVariable() =
access.(Namespace).getModuleSelfVariable()
or
not access instanceof Namespace and
result.asExpr().getExpr() = access
}

cached
Expand Down
19 changes: 19 additions & 0 deletions ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
private import codeql.ssa.Ssa as SsaImplCommon
private import codeql.ruby.AST
private import codeql.ruby.CFG as Cfg
private import codeql.ruby.controlflow.internal.ControlFlowGraphImplShared as ControlFlowGraphImplShared
private import codeql.ruby.ast.Variable
private import Cfg::CfgNodes::ExprNodes

Expand Down Expand Up @@ -53,6 +54,9 @@ private module SsaInput implements SsaImplCommon::InputSig {
or
capturedExitRead(bb, i, v) and
certain = false
or
namespaceSelfExitRead(bb, i, v) and
certain = false
}
}

Expand Down Expand Up @@ -94,6 +98,21 @@ private predicate capturedExitRead(Cfg::AnnotatedExitBasicBlock bb, int i, Local
i = bb.length()
}

/**
* Holds if a pseudo read of namespace self-variable `v` should be inserted
* at index `i` in basic block `bb`. We do this to ensure that namespace
* self-variables always get an SSA definition.
*/
private predicate namespaceSelfExitRead(Cfg::AnnotatedExitBasicBlock bb, int i, SelfVariable v) {
exists(Namespace ns, AstNode last |
v.getDeclaringScope() = ns and
last = ControlFlowGraphImplShared::getAControlFlowExitNode(ns) and
if last = ns
then bb.getNode(i).getAPredecessor().getNode() = last
else bb.getNode(i).getNode() = last
)
}

/**
* Holds if captured variable `v` is read directly inside `scope`,
* or inside a (transitively) nested scope of `scope`.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
track
| type_tracker.rb:1:1:10:3 | Container | type tracker without call steps | type_tracker.rb:1:1:10:3 | Container |
| type_tracker.rb:1:1:10:3 | self (Container) | type tracker without call steps | type_tracker.rb:1:1:10:3 | self (Container) |
| type_tracker.rb:1:1:10:3 | self (type_tracker.rb) | type tracker with call steps | type_tracker.rb:18:1:21:3 | self (positional) |
| type_tracker.rb:1:1:10:3 | self (type_tracker.rb) | type tracker with call steps | type_tracker.rb:18:1:21:3 | self in positional |
| type_tracker.rb:1:1:10:3 | self (type_tracker.rb) | type tracker with call steps | type_tracker.rb:25:1:28:3 | self (keyword) |
Expand Down Expand Up @@ -357,7 +357,7 @@ track
| type_tracker.rb:52:5:52:13 | ...[...] | type tracker without call steps | type_tracker.rb:34:1:53:3 | return return in throughArray |
| type_tracker.rb:52:5:52:13 | ...[...] | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
trackEnd
| type_tracker.rb:1:1:10:3 | Container | type_tracker.rb:1:1:10:3 | Container |
| type_tracker.rb:1:1:10:3 | self (Container) | type_tracker.rb:1:1:10:3 | self (Container) |
| type_tracker.rb:1:1:10:3 | self (type_tracker.rb) | type_tracker.rb:1:1:10:3 | self (type_tracker.rb) |
| type_tracker.rb:1:1:10:3 | self (type_tracker.rb) | type_tracker.rb:18:1:21:3 | self (positional) |
| type_tracker.rb:1:1:10:3 | self (type_tracker.rb) | type_tracker.rb:18:1:21:3 | self in positional |
Expand Down

0 comments on commit a213e9e

Please sign in to comment.