Flow for captured local variables

This commit is contained in:
Arthur Baars
2021-05-12 21:06:41 +02:00
parent e46755021b
commit 578b94453d
2 changed files with 53 additions and 1 deletions

View File

@@ -176,6 +176,49 @@ private module Cached {
)
}
/**
* Holds if there is flow for a captured variable from the enclosing scope into a block.
* ```rb
* foo = 0
* bar {
* puts foo
* }
* ```
*/
cached
predicate captureFlowIn(Definition def, Definition entry) {
exists(LocalVariable v, BasicBlock bb, int i |
ssaDefReachesRead(v, def, bb, i) and
capturedCallRead(bb, i, v) and
exists(BasicBlock bb2, int i2 |
capturedEntryWrite(bb2, i2, v) and
entry.definesAt(v, bb2, i2)
)
)
}
/**
* Holds if there is outgoinh flow for a captured variable that is updated in a block.
* ```rb
* foo = 0
* bar {
* foo += 10
* }
* puts foo
* ```
*/
cached
predicate captureFlowOut(Definition def, Definition exit) {
exists(LocalVariable v, BasicBlock bb, int i |
ssaDefReachesRead(v, def, bb, i) and
capturedExitRead(bb, i, v) and
exists(BasicBlock bb2, int i2 |
capturedCallWrite(bb2, i2, v) and
exit.definesAt(v, bb2, i2)
)
)
}
cached
Definition phiHasInputFromBlock(PhiNode phi, BasicBlock bb) {
phiHasInputFromBlock(phi, result, bb)

View File

@@ -3,6 +3,7 @@ private import codeql_ruby.dataflow.internal.DataFlowImplCommon as DataFlowImplC
private import codeql_ruby.dataflow.internal.DataFlowPublic as DataFlowPublic
private import codeql_ruby.dataflow.internal.DataFlowPrivate as DataFlowPrivate
private import codeql_ruby.dataflow.internal.DataFlowDispatch as DataFlowDispatch
private import codeql_ruby.dataflow.internal.SsaImpl as SsaImpl
private import codeql_ruby.controlflow.CfgNodes
class Node = DataFlowPublic::Node;
@@ -11,7 +12,15 @@ class LocalSourceNode = DataFlowPublic::LocalSourceNode;
predicate simpleLocalFlowStep = DataFlowPrivate::simpleLocalFlowStep/2;
predicate jumpStep = DataFlowPrivate::jumpStep/2;
predicate jumpStep(Node nodeFrom, Node nodeTo) {
DataFlowPrivate::jumpStep(nodeFrom, nodeTo)
or
SsaImpl::captureFlowIn(nodeFrom.(DataFlowPrivate::SsaDefinitionNode).getDefinition(),
nodeTo.(DataFlowPrivate::SsaDefinitionNode).getDefinition())
or
SsaImpl::captureFlowOut(nodeFrom.(DataFlowPrivate::SsaDefinitionNode).getDefinition(),
nodeTo.(DataFlowPrivate::SsaDefinitionNode).getDefinition())
}
/**
* Gets the name of a possible piece of content. This will usually include things like