mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Ruby: Reimplement flow through captured variables using field flow
This commit is contained in:
@@ -11,8 +11,6 @@ private module Input implements InputSig<RubyDataFlow> {
|
||||
predicate postWithInFlowExclude(Node n) { n instanceof FlowSummaryNode }
|
||||
|
||||
predicate argHasPostUpdateExclude(ArgumentNode n) {
|
||||
n instanceof BlockArgumentNode
|
||||
or
|
||||
n instanceof FlowSummaryNode
|
||||
or
|
||||
n instanceof SynthHashSplatArgumentNode
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import codeql.ruby.ast.Variable
|
||||
import codeql.ruby.dataflow.internal.DataFlowPrivate::VariableCapture::Flow::ConsistencyChecks
|
||||
|
||||
query predicate ambiguousVariable(VariableAccess access, Variable variable) {
|
||||
access.getVariable() = variable and
|
||||
|
||||
@@ -117,6 +117,17 @@ class MethodCall extends Call instanceof MethodCallImpl {
|
||||
*/
|
||||
final Block getBlock() { result = super.getBlockImpl() }
|
||||
|
||||
/**
|
||||
* Gets the block argument of this method call, if any.
|
||||
* ```rb
|
||||
* foo(&block)
|
||||
* ```
|
||||
*/
|
||||
final BlockArgument getBlockArgument() { result = this.getAnArgument() }
|
||||
|
||||
/** Holds if this method call has a block or block argument. */
|
||||
final predicate hasBlock() { exists(this.getBlock()) or exists(this.getBlockArgument()) }
|
||||
|
||||
/**
|
||||
* Holds if the safe navigation operator (`&.`) is used in this call.
|
||||
* ```rb
|
||||
|
||||
@@ -202,7 +202,10 @@ module ExprNodes {
|
||||
override LhsExpr getExpr() { result = super.getExpr() }
|
||||
|
||||
/** Gets a variable used in (or introduced by) this LHS. */
|
||||
Variable getAVariable() { result = e.(VariableAccess).getVariable() }
|
||||
deprecated Variable getAVariable() { result = e.(VariableAccess).getVariable() }
|
||||
|
||||
/** Gets the variable used in (or introduced by) this LHS. */
|
||||
Variable getVariable() { result = e.(VariableAccess).getVariable() }
|
||||
}
|
||||
|
||||
private class AssignExprChildMapping extends ExprChildMapping, AssignExpr {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/** Provides classes and predicates for defining flow summaries. */
|
||||
|
||||
import codeql.ruby.AST
|
||||
private import codeql.ruby.CFG
|
||||
private import codeql.ruby.typetracking.TypeTracker
|
||||
import codeql.ruby.DataFlow
|
||||
private import internal.FlowSummaryImpl as Impl
|
||||
private import internal.DataFlowDispatch
|
||||
@@ -158,3 +160,66 @@ abstract class SimpleSummarizedCallable extends SummarizedCallable {
|
||||
}
|
||||
|
||||
class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack;
|
||||
|
||||
/**
|
||||
* Provides a set of special flow summaries to ensure that callbacks passed into
|
||||
* library methods will be passed as `self` arguments into themeselves. That is,
|
||||
* we are assuming that callbacks passed into library methods will be called, which is
|
||||
* needed for flow through captured variables.
|
||||
*/
|
||||
private module LibraryCallbackSummaries {
|
||||
private predicate libraryCall(CfgNodes::ExprNodes::CallCfgNode call) {
|
||||
not exists(getTarget(call))
|
||||
}
|
||||
|
||||
private class LibraryBlockMethod extends SummarizedCallable {
|
||||
LibraryBlockMethod() { this = "<library method accepting a block>" }
|
||||
|
||||
final override MethodCall getACall() {
|
||||
libraryCall(result.getAControlFlowNode()) and
|
||||
result.hasBlock()
|
||||
}
|
||||
|
||||
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[block]" and
|
||||
output = "Argument[block].Parameter[lambda-self]" and
|
||||
preservesValue = true
|
||||
}
|
||||
}
|
||||
|
||||
private DataFlow::LocalSourceNode trackLambdaCreation(TypeTracker t) {
|
||||
t.start() and
|
||||
lambdaCreation(result, TLambdaCallKind(), _)
|
||||
or
|
||||
exists(TypeTracker t2 | result = trackLambdaCreation(t2).track(t2, t)) and
|
||||
not result instanceof DataFlow::SelfParameterNode
|
||||
}
|
||||
|
||||
private predicate libraryCallHasLambdaArg(CfgNodes::ExprNodes::CallCfgNode call, int i) {
|
||||
exists(CfgNodes::ExprCfgNode arg |
|
||||
arg = call.getArgument(i) and
|
||||
arg = trackLambdaCreation(TypeTracker::end()).getALocalUse().asExpr() and
|
||||
libraryCall(call) and
|
||||
not arg instanceof CfgNodes::ExprNodes::BlockArgumentCfgNode
|
||||
)
|
||||
}
|
||||
|
||||
private class LibraryLambdaMethod extends SummarizedCallable {
|
||||
private int i;
|
||||
|
||||
LibraryLambdaMethod() {
|
||||
this = "<library method accepting a lambda at index " + i + ">" and
|
||||
i in [0 .. 10]
|
||||
}
|
||||
|
||||
final override MethodCall getACall() {
|
||||
libraryCallHasLambdaArg(result.getAControlFlowNode(), i)
|
||||
}
|
||||
|
||||
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[" + i + "]" and
|
||||
output = "Argument[" + i + "].Parameter[lambda-self]" and
|
||||
preservesValue = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ private class SelfLocalSourceNode extends DataFlow::LocalSourceNode {
|
||||
SelfLocalSourceNode() {
|
||||
self = this.(SelfParameterNodeImpl).getSelfVariable()
|
||||
or
|
||||
self = this.(SsaSelfDefinitionNode).getVariable() and
|
||||
not LocalFlow::localFlowSsaParamInput(_, this)
|
||||
self = this.(SsaSelfDefinitionNode).getVariable()
|
||||
}
|
||||
|
||||
/** Gets the `self` variable. */
|
||||
@@ -424,6 +423,7 @@ private module Cached {
|
||||
cached
|
||||
newtype TArgumentPosition =
|
||||
TSelfArgumentPosition() or
|
||||
TLambdaSelfArgumentPosition() or
|
||||
TBlockArgumentPosition() or
|
||||
TPositionalArgumentPosition(int pos) {
|
||||
exists(Call c | exists(c.getArgument(pos)))
|
||||
@@ -446,6 +446,7 @@ private module Cached {
|
||||
cached
|
||||
newtype TParameterPosition =
|
||||
TSelfParameterPosition() or
|
||||
TLambdaSelfParameterPosition() or
|
||||
TBlockParameterPosition() or
|
||||
TPositionalParameterPosition(int pos) {
|
||||
pos = any(Parameter p).getPosition()
|
||||
@@ -941,20 +942,24 @@ private module TrackSingletonMethodOnInstanceInput implements CallGraphConstruct
|
||||
private predicate paramReturnFlow(
|
||||
DataFlow::Node nodeFrom, DataFlow::PostUpdateNode nodeTo, StepSummary summary
|
||||
) {
|
||||
exists(RelevantCall call, DataFlow::Node arg, DataFlow::ParameterNode p, Expr nodeFromPreExpr |
|
||||
exists(
|
||||
RelevantCall call, DataFlow::Node arg, DataFlow::ParameterNode p,
|
||||
CfgNodes::ExprCfgNode nodeFromPreExpr
|
||||
|
|
||||
TypeTrackerSpecific::callStep(call, arg, p) and
|
||||
nodeTo.getPreUpdateNode() = arg and
|
||||
summary.toString() = "return" and
|
||||
(
|
||||
nodeFromPreExpr = nodeFrom.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr().getExpr()
|
||||
nodeFromPreExpr = nodeFrom.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr()
|
||||
or
|
||||
nodeFromPreExpr = nodeFrom.asExpr().getExpr() and
|
||||
singletonMethodOnInstance(_, _, nodeFromPreExpr)
|
||||
nodeFromPreExpr = nodeFrom.asExpr() and
|
||||
singletonMethodOnInstance(_, _, nodeFromPreExpr.getExpr())
|
||||
)
|
||||
|
|
||||
nodeFromPreExpr = p.getParameter().(NamedParameter).getVariable().getAnAccess()
|
||||
nodeFromPreExpr =
|
||||
LocalFlow::getParameterDefNode(p.getParameter()).getDefinitionExt().getARead()
|
||||
or
|
||||
nodeFromPreExpr = p.(SelfParameterNodeImpl).getSelfVariable().getAnAccess()
|
||||
nodeFromPreExpr = p.(SelfParameterNodeImpl).getSelfDefinition().getARead()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1276,6 +1281,9 @@ class ParameterPosition extends TParameterPosition {
|
||||
/** Holds if this position represents a `self` parameter. */
|
||||
predicate isSelf() { this = TSelfParameterPosition() }
|
||||
|
||||
/** Holds if this position represents a reference to a lambda itself. Only used for tracking flow through captured variables. */
|
||||
predicate isLambdaSelf() { this = TLambdaSelfParameterPosition() }
|
||||
|
||||
/** Holds if this position represents a block parameter. */
|
||||
predicate isBlock() { this = TBlockParameterPosition() }
|
||||
|
||||
@@ -1313,6 +1321,8 @@ class ParameterPosition extends TParameterPosition {
|
||||
string toString() {
|
||||
this.isSelf() and result = "self"
|
||||
or
|
||||
this.isLambdaSelf() and result = "lambda self"
|
||||
or
|
||||
this.isBlock() and result = "block"
|
||||
or
|
||||
exists(int pos | this.isPositional(pos) and result = "position " + pos)
|
||||
@@ -1342,6 +1352,9 @@ class ArgumentPosition extends TArgumentPosition {
|
||||
/** Holds if this position represents a `self` argument. */
|
||||
predicate isSelf() { this = TSelfArgumentPosition() }
|
||||
|
||||
/** Holds if this position represents a lambda `self` argument. Only used for tracking flow through captured variables. */
|
||||
predicate isLambdaSelf() { this = TLambdaSelfArgumentPosition() }
|
||||
|
||||
/** Holds if this position represents a block argument. */
|
||||
predicate isBlock() { this = TBlockArgumentPosition() }
|
||||
|
||||
@@ -1374,6 +1387,8 @@ class ArgumentPosition extends TArgumentPosition {
|
||||
string toString() {
|
||||
this.isSelf() and result = "self"
|
||||
or
|
||||
this.isLambdaSelf() and result = "lambda self"
|
||||
or
|
||||
this.isBlock() and result = "block"
|
||||
or
|
||||
exists(int pos | this.isPositional(pos) and result = "position " + pos)
|
||||
@@ -1393,16 +1408,24 @@ class ArgumentPosition extends TArgumentPosition {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterPositionIsNotSelf(ParameterPosition ppos) { not ppos.isSelf() }
|
||||
private predicate parameterPositionIsNotSelf(ParameterPosition ppos) {
|
||||
not ppos.isSelf() and
|
||||
not ppos.isLambdaSelf()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argumentPositionIsNotSelf(ArgumentPosition apos) { not apos.isSelf() }
|
||||
private predicate argumentPositionIsNotSelf(ArgumentPosition apos) {
|
||||
not apos.isSelf() and
|
||||
not apos.isLambdaSelf()
|
||||
}
|
||||
|
||||
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
|
||||
pragma[nomagic]
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
|
||||
ppos.isSelf() and apos.isSelf()
|
||||
or
|
||||
ppos.isLambdaSelf() and apos.isLambdaSelf()
|
||||
or
|
||||
ppos.isBlock() and apos.isBlock()
|
||||
or
|
||||
exists(int pos | ppos.isPositional(pos) and apos.isPositional(pos))
|
||||
@@ -1441,8 +1464,6 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
|
||||
* This is a temporary hook to support technical debt in the Go language; do not use.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate golangSpecificParamArgFilter(
|
||||
DataFlowCall call, DataFlow::ParameterNode p, ArgumentNode arg
|
||||
) {
|
||||
predicate golangSpecificParamArgFilter(DataFlowCall call, ParameterNodeImpl p, ArgumentNode arg) {
|
||||
any()
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ module RubyDataFlow implements InputSig {
|
||||
import Private
|
||||
import Public
|
||||
|
||||
// includes `LambdaSelfParameterNode`, which is not part of the public API
|
||||
class ParameterNode = Private::ParameterNodeImpl;
|
||||
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
Private::isParameterNode(p, c, pos)
|
||||
}
|
||||
|
||||
@@ -83,13 +83,13 @@ module LocalFlow {
|
||||
def instanceof Ssa::PhiNode
|
||||
or
|
||||
def instanceof SsaImpl::PhiReadNode
|
||||
//TODO: or def instanceof LocalFlow::UncertainExplicitSsaDefinition
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `nodeFrom` is a node for SSA definition `def`, which can reach `next`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate localFlowSsaInputFromDef(
|
||||
SsaDefinitionExtNode nodeFrom, SsaImpl::DefinitionExt def, SsaInputDefinitionExtNode next
|
||||
) {
|
||||
@@ -102,20 +102,23 @@ module LocalFlow {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `exprFrom` is a last read of SSA definition `def`, which
|
||||
* Holds if `nodeFrom` is a last read of SSA definition `def`, which
|
||||
* can reach `next`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate localFlowSsaInputFromRead(
|
||||
CfgNodes::ExprCfgNode exprFrom, SsaImpl::DefinitionExt def, SsaInputDefinitionExtNode next
|
||||
SsaImpl::DefinitionExt def, Node nodeFrom, SsaInputDefinitionExtNode next
|
||||
) {
|
||||
exists(BasicBlock bb, int i |
|
||||
exists(BasicBlock bb, int i, CfgNodes::ExprCfgNode exprFrom |
|
||||
SsaImpl::lastRefBeforeRedefExt(def, bb, i, next.getDefinitionExt()) and
|
||||
exprFrom = bb.getNode(i) and
|
||||
exprFrom.getExpr() instanceof VariableReadAccess
|
||||
exprFrom.getExpr() instanceof VariableReadAccess and
|
||||
exprFrom = [nodeFrom.asExpr(), nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr()]
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the SSA definition node corresponding to parameter `p`. */
|
||||
pragma[nomagic]
|
||||
SsaDefinitionExtNode getParameterDefNode(NamedParameter p) {
|
||||
exists(BasicBlock bb, int i |
|
||||
bb.getNode(i).getAstNode() = p.getDefiningAccess() and
|
||||
@@ -123,18 +126,14 @@ module LocalFlow {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the SSA definition node corresponding to the implicit `self` parameter for `m`. */
|
||||
private SsaDefinitionExtNode getSelfParameterDefNode(MethodBase m) {
|
||||
result.getDefinitionExt().(Ssa::SelfDefinition).getSourceVariable().getDeclaringScope() = m
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `nodeFrom` is a parameter node, and `nodeTo` is a corresponding SSA node.
|
||||
*/
|
||||
predicate localFlowSsaParamInput(Node nodeFrom, SsaDefinitionExtNode nodeTo) {
|
||||
nodeTo = getParameterDefNode(nodeFrom.(ParameterNodeImpl).getParameter())
|
||||
pragma[nomagic]
|
||||
predicate localFlowSsaParamInput(ParameterNodeImpl nodeFrom, SsaDefinitionExtNode nodeTo) {
|
||||
nodeTo = getParameterDefNode(nodeFrom.getParameter())
|
||||
or
|
||||
nodeTo = getSelfParameterDefNode(nodeFrom.(SelfParameterNodeImpl).getMethod())
|
||||
nodeTo.getDefinitionExt() = nodeFrom.(SelfParameterNodeImpl).getSelfDefinition()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,39 +146,30 @@ module LocalFlow {
|
||||
|
||||
/**
|
||||
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
|
||||
* some SSA definition.
|
||||
* SSA definition `def`.
|
||||
*/
|
||||
private predicate localSsaFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(SsaImpl::DefinitionExt def |
|
||||
// Flow from assignment into SSA definition
|
||||
def.(Ssa::WriteDefinition).assigns(nodeFrom.asExpr()) and
|
||||
nodeTo.(SsaDefinitionExtNode).getDefinitionExt() = def
|
||||
or
|
||||
// Flow from SSA definition to first read
|
||||
def = nodeFrom.(SsaDefinitionExtNode).getDefinitionExt() and
|
||||
firstReadExt(def, nodeTo.asExpr())
|
||||
or
|
||||
// Flow from read to next read
|
||||
localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
|
||||
or
|
||||
// Flow into phi (read) SSA definition node from def
|
||||
localFlowSsaInputFromDef(nodeFrom, def, nodeTo)
|
||||
)
|
||||
pragma[nomagic]
|
||||
predicate localSsaFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
|
||||
// Flow from assignment into SSA definition
|
||||
def.(Ssa::WriteDefinition).assigns(nodeFrom.asExpr()) and
|
||||
nodeTo.(SsaDefinitionExtNode).getDefinitionExt() = def
|
||||
or
|
||||
localFlowSsaParamInput(nodeFrom, nodeTo)
|
||||
// TODO
|
||||
// or
|
||||
// // Flow into uncertain SSA definition
|
||||
// exists(LocalFlow::UncertainExplicitSsaDefinition uncertain |
|
||||
// localFlowSsaInput(nodeFrom, def, uncertain) and
|
||||
// uncertain = nodeTo.(SsaDefinitionNode).getDefinition() and
|
||||
// def = uncertain.getPriorDefinition()
|
||||
// )
|
||||
// Flow from SSA definition to first read
|
||||
def = nodeFrom.(SsaDefinitionExtNode).getDefinitionExt() and
|
||||
firstReadExt(def, nodeTo.asExpr())
|
||||
or
|
||||
// Flow from post-update read to next read
|
||||
localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
|
||||
or
|
||||
// Flow into phi (read) SSA definition node from def
|
||||
localFlowSsaInputFromDef(nodeFrom, def, nodeTo)
|
||||
or
|
||||
localFlowSsaParamInput(nodeFrom, nodeTo) and
|
||||
def = nodeTo.(SsaDefinitionExtNode).getDefinitionExt()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
|
||||
localSsaFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::BlockArgumentCfgNode).getValue()
|
||||
or
|
||||
nodeFrom.asExpr() = getALastEvalNode(nodeTo.asExpr())
|
||||
@@ -218,7 +208,7 @@ module LocalFlow {
|
||||
}
|
||||
}
|
||||
|
||||
/** An argument of a call (including qualifier arguments, excluding block arguments). */
|
||||
/** An argument of a call (including qualifier arguments and block arguments). */
|
||||
private class Argument extends CfgNodes::ExprCfgNode {
|
||||
private CfgNodes::ExprNodes::CallCfgNode call;
|
||||
private ArgumentPosition arg;
|
||||
@@ -239,7 +229,11 @@ private class Argument extends CfgNodes::ExprCfgNode {
|
||||
arg.isKeyword(p.getKey().getConstantValue().getSymbol())
|
||||
)
|
||||
or
|
||||
this = call.getReceiver() and arg.isSelf()
|
||||
this = call.getReceiver() and
|
||||
arg.isSelf()
|
||||
or
|
||||
lambdaCallExpr(call, this) and
|
||||
arg.isLambdaSelf()
|
||||
or
|
||||
this = call.getAnArgument() and
|
||||
this.getExpr() instanceof HashSplatExpr and
|
||||
@@ -250,6 +244,13 @@ private class Argument extends CfgNodes::ExprCfgNode {
|
||||
this.getExpr() instanceof SplatExpr and
|
||||
arg.isSplat(pos)
|
||||
)
|
||||
or
|
||||
this = call.getAnArgument() and
|
||||
this.getExpr() instanceof BlockArgument and
|
||||
arg.isBlock()
|
||||
or
|
||||
this = call.getBlock() and
|
||||
arg.isBlock()
|
||||
}
|
||||
|
||||
/** Holds if this expression is the `i`th argument of `c`. */
|
||||
@@ -266,16 +267,127 @@ predicate isNonConstantExpr(CfgNodes::ExprCfgNode n) {
|
||||
|
||||
/** Provides logic related to captured variables. */
|
||||
module VariableCapture {
|
||||
class CapturedVariable extends LocalVariable {
|
||||
CapturedVariable() { this.isCaptured() }
|
||||
private import codeql.dataflow.VariableCapture as Shared
|
||||
|
||||
CfgScope getCfgScope() {
|
||||
exists(Scope scope | scope = this.getDeclaringScope() |
|
||||
result = scope
|
||||
or
|
||||
result = scope.(ModuleBase).getCfgScope()
|
||||
)
|
||||
private predicate closureFlowStep(CfgNodes::ExprCfgNode e1, CfgNodes::ExprCfgNode e2) {
|
||||
e1 = getALastEvalNode(e2)
|
||||
or
|
||||
exists(Ssa::Definition def |
|
||||
def.getARead() = e2 and
|
||||
def.getAnUltimateDefinition().(Ssa::WriteDefinition).assigns(e1)
|
||||
)
|
||||
}
|
||||
|
||||
private module CaptureInput implements Shared::InputSig {
|
||||
private import ruby as R
|
||||
private import codeql.ruby.controlflow.ControlFlowGraph
|
||||
private import codeql.ruby.controlflow.BasicBlocks as BasicBlocks
|
||||
|
||||
class Location = R::Location;
|
||||
|
||||
class BasicBlock extends BasicBlocks::BasicBlock {
|
||||
Callable getEnclosingCallable() { result = this.getScope() }
|
||||
}
|
||||
|
||||
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
|
||||
result = bb.getImmediateDominator()
|
||||
}
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
|
||||
|
||||
class CapturedVariable extends LocalVariable {
|
||||
CapturedVariable() { this.isCaptured() }
|
||||
|
||||
Callable getCallable() {
|
||||
exists(Scope scope | scope = this.getDeclaringScope() |
|
||||
result = scope
|
||||
or
|
||||
result = scope.(ModuleBase).getCfgScope()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CapturedParameter extends CapturedVariable {
|
||||
abstract ParameterNode getParameterNode();
|
||||
}
|
||||
|
||||
private class CapturedNamedParameter extends CapturedParameter {
|
||||
private NamedParameter p;
|
||||
|
||||
CapturedNamedParameter() { this = p.getVariable() }
|
||||
|
||||
override ParameterNode getParameterNode() { result.asParameter() = p }
|
||||
}
|
||||
|
||||
private class CapturedSelfParameter extends CapturedParameter, SelfVariable {
|
||||
override SelfParameterNode getParameterNode() { this = result.getSelfVariable() }
|
||||
}
|
||||
|
||||
class Expr extends CfgNodes::ExprCfgNode {
|
||||
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) }
|
||||
}
|
||||
|
||||
class VariableWrite extends Expr, CfgNodes::ExprNodes::AssignExprCfgNode {
|
||||
CapturedVariable v;
|
||||
|
||||
VariableWrite() { v = this.getLhs().getVariable() }
|
||||
|
||||
CapturedVariable getVariable() { result = v }
|
||||
}
|
||||
|
||||
class VariableRead extends Expr instanceof CfgNodes::ExprNodes::LocalVariableReadAccessCfgNode {
|
||||
CapturedVariable v;
|
||||
|
||||
VariableRead() { v = super.getVariable() }
|
||||
|
||||
CapturedVariable getVariable() { result = v }
|
||||
}
|
||||
|
||||
class ClosureExpr extends Expr {
|
||||
Callable c;
|
||||
|
||||
ClosureExpr() { lambdaCreationExpr(this, _, c) }
|
||||
|
||||
predicate hasBody(Callable body) { body = c }
|
||||
|
||||
predicate hasAliasedAccess(Expr f) { closureFlowStep+(this, f) and not closureFlowStep(f, _) }
|
||||
}
|
||||
|
||||
class Callable extends CfgScope {
|
||||
predicate isConstructor() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
class CapturedVariable = CaptureInput::CapturedVariable;
|
||||
|
||||
class ClosureExpr = CaptureInput::ClosureExpr;
|
||||
|
||||
module Flow = Shared::Flow<CaptureInput>;
|
||||
|
||||
private Flow::ClosureNode asClosureNode(Node n) {
|
||||
result = n.(CaptureNode).getSynthesizedCaptureNode()
|
||||
or
|
||||
result.(Flow::ExprNode).getExpr() = n.asExpr()
|
||||
or
|
||||
result.(Flow::VariableWriteSourceNode).getVariableWrite().getRhs() = n.asExpr()
|
||||
or
|
||||
result.(Flow::ExprPostUpdateNode).getExpr() = n.(PostUpdateNode).getPreUpdateNode().asExpr()
|
||||
or
|
||||
result.(Flow::ParameterNode).getParameter().getParameterNode() = n
|
||||
or
|
||||
result.(Flow::ThisParameterNode).getCallable() = n.(LambdaSelfParameterNode).getCallable()
|
||||
}
|
||||
|
||||
predicate storeStep(Node node1, Content::CapturedVariableContent c, Node node2) {
|
||||
Flow::storeStep(asClosureNode(node1), c.getVariable(), asClosureNode(node2))
|
||||
}
|
||||
|
||||
predicate readStep(Node node1, Content::CapturedVariableContent c, Node node2) {
|
||||
Flow::readStep(asClosureNode(node1), c.getVariable(), asClosureNode(node2))
|
||||
}
|
||||
|
||||
predicate valueStep(Node node1, Node node2) {
|
||||
Flow::localFlowStep(asClosureNode(node1), asClosureNode(node2))
|
||||
}
|
||||
|
||||
class CapturedSsaDefinitionExt extends SsaImpl::DefinitionExt {
|
||||
@@ -331,6 +443,7 @@ private module Cached {
|
||||
p instanceof SplatParameter
|
||||
} or
|
||||
TSelfParameterNode(MethodBase m) or
|
||||
TLambdaSelfParameterNode(Callable c) { lambdaCreationExpr(_, _, c) } or
|
||||
TBlockParameterNode(MethodBase m) or
|
||||
TSynthHashSplatParameterNode(DataFlowCallable c) {
|
||||
isParameterNode(_, c, any(ParameterPosition p | p.isKeyword(_)))
|
||||
@@ -366,7 +479,8 @@ private module Cached {
|
||||
TSynthSplatArgumentNode(CfgNodes::ExprNodes::CallCfgNode c) {
|
||||
exists(Argument arg, ArgumentPosition pos | pos.isPositional(_) | arg.isArgumentOf(c, pos)) and
|
||||
not exists(Argument arg, ArgumentPosition pos | pos.isSplat(_) | arg.isArgumentOf(c, pos))
|
||||
}
|
||||
} or
|
||||
TCaptureNode(VariableCapture::Flow::SynthesizedCaptureNode cn)
|
||||
|
||||
class TSourceParameterNode =
|
||||
TNormalParameterNode or TBlockParameterNode or TSelfParameterNode or
|
||||
@@ -386,21 +500,23 @@ private module Cached {
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
|
||||
or
|
||||
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
|
||||
or
|
||||
// Flow into phi node from read
|
||||
exists(CfgNodes::ExprCfgNode exprFrom |
|
||||
LocalFlow::localFlowSsaInputFromRead(exprFrom, _, nodeTo)
|
||||
exists(SsaImpl::DefinitionExt def |
|
||||
// captured variables are handled by the shared `VariableCapture` library
|
||||
not def instanceof VariableCapture::CapturedSsaDefinitionExt
|
||||
|
|
||||
exprFrom = nodeFrom.asExpr() and
|
||||
LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo)
|
||||
or
|
||||
LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
|
||||
or
|
||||
exprFrom = nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr()
|
||||
LocalFlow::localFlowSsaInputFromRead(def, nodeFrom, nodeTo) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
|
||||
or
|
||||
VariableCapture::valueStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
/** This is the local flow predicate that is exposed. */
|
||||
@@ -408,6 +524,8 @@ private module Cached {
|
||||
predicate localFlowStepImpl(Node nodeFrom, Node nodeTo) {
|
||||
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
|
||||
or
|
||||
LocalFlow::localSsaFlowStep(_, nodeFrom, nodeTo)
|
||||
or
|
||||
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
|
||||
or
|
||||
// Simple flow through library code is included in the exposed local
|
||||
@@ -422,13 +540,11 @@ private module Cached {
|
||||
predicate localFlowStepTypeTracker(Node nodeFrom, Node nodeTo) {
|
||||
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
|
||||
or
|
||||
LocalFlow::localSsaFlowStep(_, nodeFrom, nodeTo)
|
||||
or
|
||||
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
|
||||
or
|
||||
// Flow into phi node from read
|
||||
exists(CfgNodes::ExprCfgNode exprFrom |
|
||||
LocalFlow::localFlowSsaInputFromRead(exprFrom, _, nodeTo) and
|
||||
exprFrom = [nodeFrom.asExpr(), nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr()]
|
||||
)
|
||||
LocalFlow::localFlowSsaInputFromRead(_, nodeFrom, nodeTo)
|
||||
or
|
||||
VariableCapture::flowInsensitiveStep(nodeFrom, nodeTo)
|
||||
}
|
||||
@@ -527,6 +643,7 @@ private module Cached {
|
||||
name = [input, output].regexpFind("(?<=(^|\\.)Field\\[)[^\\]]+(?=\\])", _, _).trim()
|
||||
)
|
||||
} or
|
||||
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
|
||||
// Only used by type-tracking
|
||||
TAttributeName(string name) { name = any(SetterMethodCall c).getTargetName() }
|
||||
|
||||
@@ -549,7 +666,8 @@ private module Cached {
|
||||
TUnknownElementContentApprox() or
|
||||
TKnownIntegerElementContentApprox() or
|
||||
TKnownElementContentApprox(string approx) { approx = approxKnownElementIndex(_) } or
|
||||
TNonElementContentApprox(Content c) { not c instanceof Content::ElementContent }
|
||||
TNonElementContentApprox(Content c) { not c instanceof Content::ElementContent } or
|
||||
TCapturedVariableContentApprox(VariableCapture::CapturedVariable v)
|
||||
}
|
||||
|
||||
class TElementContent = TKnownElementContent or TUnknownElementContent;
|
||||
@@ -577,6 +695,10 @@ predicate nodeIsHidden(Node n) {
|
||||
n instanceof SynthSplatArgParameterNode
|
||||
or
|
||||
n instanceof SynthSplatParameterElementNode
|
||||
or
|
||||
n instanceof LambdaSelfParameterNode
|
||||
or
|
||||
n instanceof CaptureNode
|
||||
}
|
||||
|
||||
/** An SSA definition, viewed as a node in a data flow graph. */
|
||||
@@ -624,7 +746,7 @@ class CapturedVariableNode extends NodeImpl, TCapturedVariableNode {
|
||||
/** Gets the captured variable represented by this node. */
|
||||
VariableCapture::CapturedVariable getVariable() { result = variable }
|
||||
|
||||
override CfgScope getCfgScope() { result = variable.getCfgScope() }
|
||||
override CfgScope getCfgScope() { result = variable.getCallable() }
|
||||
|
||||
override Location getLocationImpl() { result = variable.getLocation() }
|
||||
|
||||
@@ -653,6 +775,24 @@ class ReturningStatementNode extends NodeImpl, TReturningNode {
|
||||
override string toStringImpl() { result = n.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A synthesized data flow node representing a closure object that tracks
|
||||
* captured variables.
|
||||
*/
|
||||
class CaptureNode extends NodeImpl, TCaptureNode {
|
||||
private VariableCapture::Flow::SynthesizedCaptureNode cn;
|
||||
|
||||
CaptureNode() { this = TCaptureNode(cn) }
|
||||
|
||||
VariableCapture::Flow::SynthesizedCaptureNode getSynthesizedCaptureNode() { result = cn }
|
||||
|
||||
override CfgScope getCfgScope() { result = cn.getEnclosingCallable() }
|
||||
|
||||
override Location getLocationImpl() { result = cn.getLocation() }
|
||||
|
||||
override string toStringImpl() { result = cn.toString() }
|
||||
}
|
||||
|
||||
private module ParameterNodes {
|
||||
abstract class ParameterNodeImpl extends NodeImpl {
|
||||
abstract Parameter getParameter();
|
||||
@@ -722,6 +862,11 @@ private module ParameterNodes {
|
||||
|
||||
final MethodBase getMethod() { result = method }
|
||||
|
||||
/** Gets the corresponding SSA `self` definition, if any. */
|
||||
Ssa::SelfDefinition getSelfDefinition() {
|
||||
result.getSourceVariable().getDeclaringScope() = method
|
||||
}
|
||||
|
||||
/** Gets the underlying `self` variable. */
|
||||
final SelfVariable getSelfVariable() { result.getDeclaringScope() = method }
|
||||
|
||||
@@ -735,14 +880,43 @@ private module ParameterNodes {
|
||||
|
||||
override Location getLocationImpl() { result = method.getLocation() }
|
||||
|
||||
override string toStringImpl() { result = "self in " + method.toString() }
|
||||
override string toStringImpl() { result = "self in " + method }
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of a lambda itself at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*
|
||||
* This is used for tracking flow through captured variables, and we use a
|
||||
* separate node and parameter/argument positions in order to distinguish
|
||||
* "lambda self" from "normal self", as lambdas may also access outer `self`
|
||||
* variables (through variable capture).
|
||||
*/
|
||||
class LambdaSelfParameterNode extends ParameterNodeImpl, TLambdaSelfParameterNode {
|
||||
private Callable callable;
|
||||
|
||||
LambdaSelfParameterNode() { this = TLambdaSelfParameterNode(callable) }
|
||||
|
||||
final Callable getCallable() { result = callable }
|
||||
|
||||
override Parameter getParameter() { none() }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
callable = c.asCallable() and pos.isLambdaSelf()
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { result = callable }
|
||||
|
||||
override Location getLocationImpl() { result = callable.getLocation() }
|
||||
|
||||
override string toStringImpl() { result = "lambda self in " + callable }
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of a block parameter at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class BlockParameterNode extends ParameterNodeImpl, TBlockParameterNode {
|
||||
class BlockParameterNode extends ParameterNodeImpl, ArgumentNode, TBlockParameterNode {
|
||||
private MethodBase method;
|
||||
|
||||
BlockParameterNode() { this = TBlockParameterNode(method) }
|
||||
@@ -757,6 +931,20 @@ private module ParameterNodes {
|
||||
c.asCallable() = method and pos.isBlock()
|
||||
}
|
||||
|
||||
CfgNodes::ExprNodes::CallCfgNode getAYieldCall() {
|
||||
this.getMethod() = result.getExpr().(YieldCall).getEnclosingMethod()
|
||||
}
|
||||
|
||||
// needed for variable capture flow
|
||||
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
|
||||
call = this.getAYieldCall() and
|
||||
pos.isLambdaSelf()
|
||||
}
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
this.sourceArgumentOf(call.asCall(), pos)
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { result = method }
|
||||
|
||||
override Location getLocationImpl() {
|
||||
@@ -1027,36 +1215,6 @@ private module ArgumentNodes {
|
||||
}
|
||||
}
|
||||
|
||||
/** A data-flow node that represents the `self` argument of a call. */
|
||||
class SelfArgumentNode extends ExplicitArgumentNode {
|
||||
SelfArgumentNode() { arg.isArgumentOf(_, any(ArgumentPosition pos | pos.isSelf())) }
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a block argument. */
|
||||
class BlockArgumentNode extends ArgumentNode {
|
||||
BlockArgumentNode() {
|
||||
this.asExpr().getExpr() instanceof BlockArgument or
|
||||
exists(CfgNodes::ExprNodes::CallCfgNode c | c.getBlock() = this.asExpr())
|
||||
}
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
this.sourceArgumentOf(call.asCall(), pos)
|
||||
}
|
||||
|
||||
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
|
||||
pos.isBlock() and
|
||||
(
|
||||
this.asExpr() = call.getBlock()
|
||||
or
|
||||
exists(CfgNodes::ExprCfgNode arg |
|
||||
arg = call.getAnArgument() and
|
||||
this.asExpr() = arg and
|
||||
arg.getExpr() instanceof BlockArgument
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
|
||||
private DataFlowCall call_;
|
||||
private ArgumentPosition pos_;
|
||||
@@ -1335,7 +1493,7 @@ private module OutNodes {
|
||||
|
||||
import OutNodes
|
||||
|
||||
predicate jumpStepTypeTracker(Node pred, Node succ) {
|
||||
predicate jumpStep(Node pred, Node succ) {
|
||||
succ.asExpr().getExpr().(ConstantReadAccess).getValue() = pred.asExpr().getExpr()
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred.(FlowSummaryNode).getSummaryNode(),
|
||||
@@ -1344,16 +1502,6 @@ predicate jumpStepTypeTracker(Node pred, Node succ) {
|
||||
any(AdditionalJumpStep s).step(pred, succ)
|
||||
}
|
||||
|
||||
predicate jumpStep(Node pred, Node succ) {
|
||||
jumpStepTypeTracker(pred, succ)
|
||||
or
|
||||
SsaImpl::captureFlowIn(_, pred.(SsaDefinitionExtNode).getDefinitionExt(),
|
||||
succ.(SsaDefinitionExtNode).getDefinitionExt())
|
||||
or
|
||||
SsaImpl::captureFlowOut(_, pred.(SsaDefinitionExtNode).getDefinitionExt(),
|
||||
succ.(SsaDefinitionExtNode).getDefinitionExt())
|
||||
}
|
||||
|
||||
private ContentSet getKeywordContent(string name) {
|
||||
exists(ConstantValue::ConstantSymbolValue key |
|
||||
result.isSingleton(TKnownElementContent(key)) and
|
||||
@@ -1439,6 +1587,9 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
|
||||
)
|
||||
or
|
||||
storeStepCommon(node1, c, node2)
|
||||
or
|
||||
VariableCapture::storeStep(node1, any(Content::CapturedVariableContent v | c.isSingleton(v)),
|
||||
node2)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1487,6 +1638,8 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
c = getPositionalContent(e.getReadPosition())
|
||||
)
|
||||
or
|
||||
VariableCapture::readStep(node1, any(Content::CapturedVariableContent v | c.isSingleton(v)), node2)
|
||||
or
|
||||
readStepCommon(node1, c, node2)
|
||||
}
|
||||
|
||||
@@ -1521,27 +1674,60 @@ predicate expectsContent(Node n, ContentSet c) {
|
||||
}
|
||||
|
||||
private newtype TDataFlowType =
|
||||
TTodoDataFlowType() or
|
||||
TTodoDataFlowType2() // Add a dummy value to prevent bad functionality-induced joins arising from a type of size 1.
|
||||
TLambdaDataFlowType(Callable c) { c = any(LambdaSelfParameterNode n).getCallable() } or
|
||||
TUnknownDataFlowType()
|
||||
|
||||
class DataFlowType extends TDataFlowType {
|
||||
string toString() { result = "" }
|
||||
}
|
||||
|
||||
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
|
||||
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) {
|
||||
t1 = TLambdaDataFlowType(_) and
|
||||
t2 = TUnknownDataFlowType()
|
||||
}
|
||||
|
||||
private predicate mustHaveLambdaType(CfgNodes::ExprCfgNode e, Callable c) {
|
||||
exists(VariableCapture::ClosureExpr ce | ce.hasBody(c) |
|
||||
e = ce or
|
||||
ce.hasAliasedAccess(e)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the type of `n` used for type pruning. */
|
||||
DataFlowType getNodeType(Node n) { result = TTodoDataFlowType() and exists(n) }
|
||||
DataFlowType getNodeType(Node n) {
|
||||
result = TLambdaDataFlowType(n.(LambdaSelfParameterNode).getCallable())
|
||||
or
|
||||
exists(Callable c |
|
||||
mustHaveLambdaType(n.asExpr(), c) and
|
||||
result = TLambdaDataFlowType(c)
|
||||
)
|
||||
or
|
||||
not n instanceof LambdaSelfParameterNode and
|
||||
not mustHaveLambdaType(n.asExpr(), _) and
|
||||
result = TUnknownDataFlowType()
|
||||
}
|
||||
|
||||
/** Gets a string representation of a `DataFlowType`. */
|
||||
string ppReprType(DataFlowType t) { none() }
|
||||
|
||||
pragma[inline]
|
||||
private predicate compatibleTypesNonSymRefl(DataFlowType t1, DataFlowType t2) {
|
||||
t1 = TLambdaDataFlowType(_) and
|
||||
t2 = TUnknownDataFlowType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
||||
* a node of type `t1` to a node of type `t2`.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { any() }
|
||||
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
|
||||
t1 = t2
|
||||
or
|
||||
compatibleTypesNonSymRefl(t1, t2)
|
||||
or
|
||||
compatibleTypesNonSymRefl(t2, t1)
|
||||
}
|
||||
|
||||
abstract class PostUpdateNodeImpl extends Node {
|
||||
/** Gets the node before the state update. */
|
||||
@@ -1583,6 +1769,17 @@ private module PostUpdateNodes {
|
||||
|
||||
override Node getPreUpdateNode() { result = pre }
|
||||
}
|
||||
|
||||
private class CapturePostUpdateNode extends PostUpdateNodeImpl, CaptureNode {
|
||||
private CaptureNode pre;
|
||||
|
||||
CapturePostUpdateNode() {
|
||||
VariableCapture::Flow::capturePostUpdateNode(this.getSynthesizedCaptureNode(),
|
||||
pre.getSynthesizedCaptureNode())
|
||||
}
|
||||
|
||||
override Node getPreUpdateNode() { result = pre }
|
||||
}
|
||||
}
|
||||
|
||||
private import PostUpdateNodes
|
||||
@@ -1623,22 +1820,27 @@ newtype LambdaCallKind =
|
||||
TLambdaCallKind()
|
||||
|
||||
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
|
||||
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
|
||||
private predicate lambdaCreationExpr(CfgNodes::ExprCfgNode creation, LambdaCallKind kind, Callable c) {
|
||||
kind = TYieldCallKind() and
|
||||
creation.asExpr().getExpr() = c.asCallable().(Block)
|
||||
creation.getExpr() = c.(Block)
|
||||
or
|
||||
kind = TLambdaCallKind() and
|
||||
(
|
||||
creation.asExpr().getExpr() = c.asCallable().(Lambda)
|
||||
creation.getExpr() = c.(Lambda)
|
||||
or
|
||||
creation.asExpr() =
|
||||
creation =
|
||||
any(CfgNodes::ExprNodes::MethodCallCfgNode mc |
|
||||
c.asCallable() = mc.getBlock().getExpr() and
|
||||
c = mc.getBlock().getExpr() and
|
||||
isProcCreationCall(mc.getExpr())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
|
||||
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
|
||||
lambdaCreationExpr(creation.asExpr(), kind, c.asCallable())
|
||||
}
|
||||
|
||||
/** Holds if `call` is a call to `lambda`, `proc`, or `Proc.new` */
|
||||
pragma[nomagic]
|
||||
private predicate isProcCreationCall(MethodCall call) {
|
||||
@@ -1648,20 +1850,24 @@ private predicate isProcCreationCall(MethodCall call) {
|
||||
call.getReceiver().(ConstantReadAccess).getAQualifiedName() = "Proc"
|
||||
}
|
||||
|
||||
/** Holds if `mc` is a call to `receiver.call`. */
|
||||
private predicate lambdaCallExpr(
|
||||
CfgNodes::ExprNodes::MethodCallCfgNode mc, CfgNodes::ExprCfgNode receiver
|
||||
) {
|
||||
receiver = mc.getReceiver() and
|
||||
mc.getExpr().getMethodName() = "call"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `call` is a from-source lambda call of kind `kind` where `receiver`
|
||||
* is the lambda expression.
|
||||
*/
|
||||
predicate lambdaSourceCall(CfgNodes::ExprNodes::CallCfgNode call, LambdaCallKind kind, Node receiver) {
|
||||
kind = TYieldCallKind() and
|
||||
receiver.(BlockParameterNode).getMethod() = call.getExpr().(YieldCall).getEnclosingMethod()
|
||||
call = receiver.(BlockParameterNode).getAYieldCall()
|
||||
or
|
||||
kind = TLambdaCallKind() and
|
||||
call =
|
||||
any(CfgNodes::ExprNodes::MethodCallCfgNode mc |
|
||||
receiver.asExpr() = mc.getReceiver() and
|
||||
mc.getExpr().getMethodName() = "call"
|
||||
)
|
||||
lambdaCallExpr(call, receiver.asExpr())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1687,8 +1893,11 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
|
||||
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
|
||||
* by default as a heuristic.
|
||||
*/
|
||||
predicate allowParameterReturnInSelf(ParameterNode p) {
|
||||
predicate allowParameterReturnInSelf(ParameterNodeImpl p) {
|
||||
FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(p)
|
||||
or
|
||||
VariableCapture::Flow::heuristicAllowInstanceParameterReturnInSelf(p.(SelfParameterNode)
|
||||
.getCallable())
|
||||
}
|
||||
|
||||
/** An approximated `Content`. */
|
||||
@@ -1765,4 +1974,4 @@ class AdditionalJumpStep extends Unit {
|
||||
*
|
||||
* Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
|
||||
*/
|
||||
int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() }
|
||||
int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNodeImpl p) { none() }
|
||||
|
||||
@@ -568,6 +568,18 @@ module Content {
|
||||
|
||||
/** Gets `AttributeNameContent` of the given name. */
|
||||
AttributeNameContent getAttributeName(string name) { result.getName() = name }
|
||||
|
||||
/** A captured variable. */
|
||||
class CapturedVariableContent extends Content, TCapturedVariableContent {
|
||||
private LocalVariable v;
|
||||
|
||||
CapturedVariableContent() { this = TCapturedVariableContent(v) }
|
||||
|
||||
/** Gets the captured variable. */
|
||||
LocalVariable getVariable() { result = v }
|
||||
|
||||
override string toString() { result = "captured " + v }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -765,14 +777,14 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
* This is restricted to calls where the variable is captured inside a
|
||||
* block.
|
||||
*/
|
||||
private Ssa::Definition getAMaybeGuardedCapturedDef() {
|
||||
private Ssa::CapturedEntryDefinition getAMaybeGuardedCapturedDef() {
|
||||
exists(
|
||||
CfgNodes::ExprCfgNode g, boolean branch, CfgNodes::ExprCfgNode testedNode,
|
||||
Ssa::Definition def, CfgNodes::ExprNodes::CallCfgNode call
|
||||
|
|
||||
def.getARead() = testedNode and
|
||||
guardChecks(g, testedNode, branch) and
|
||||
SsaImpl::captureFlowIn(call, def, result) and
|
||||
def.getSourceVariable() = result.getSourceVariable() and
|
||||
guardControlsBlock(g, call.getBasicBlock(), branch) and
|
||||
result.getBasicBlock().getScope() = call.getExpr().(MethodCall).getBlock()
|
||||
)
|
||||
@@ -830,14 +842,14 @@ abstract deprecated class BarrierGuard extends CfgNodes::ExprCfgNode {
|
||||
* This is restricted to calls where the variable is captured inside a
|
||||
* block.
|
||||
*/
|
||||
private Ssa::Definition getAMaybeGuardedCapturedDef() {
|
||||
private Ssa::CapturedEntryDefinition getAMaybeGuardedCapturedDef() {
|
||||
exists(
|
||||
boolean branch, CfgNodes::ExprCfgNode testedNode, Ssa::Definition def,
|
||||
CfgNodes::ExprNodes::CallCfgNode call
|
||||
|
|
||||
def.getARead() = testedNode and
|
||||
this.checks(testedNode, branch) and
|
||||
SsaImpl::captureFlowIn(call, def, result) and
|
||||
def.getSourceVariable() = result.getSourceVariable() and
|
||||
this.controlsBlock(call.getBasicBlock(), branch) and
|
||||
result.getBasicBlock().getScope() = call.getExpr().(MethodCall).getBlock()
|
||||
)
|
||||
@@ -1208,7 +1220,10 @@ class LhsExprNode extends ExprNode {
|
||||
LhsExpr asLhsExprAstNode() { result = lhsExprCfgNode.getExpr() }
|
||||
|
||||
/** Gets a variable used in (or introduced by) this LHS. */
|
||||
Variable getAVariable() { result = lhsExprCfgNode.getAVariable() }
|
||||
deprecated Variable getAVariable() { result = lhsExprCfgNode.getAVariable() }
|
||||
|
||||
/** Gets the variable used in (or introduced by) this LHS. */
|
||||
Variable getVariable() { result = lhsExprCfgNode.getVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ class NeutralCallableBase = string;
|
||||
DataFlowCallable inject(SummarizedCallable c) { result.asLibraryCallable() = c }
|
||||
|
||||
/** Gets the parameter position representing a callback itself, if any. */
|
||||
ArgumentPosition callbackSelfParameterPosition() { none() } // disables implicit summary flow to `self` for callbacks
|
||||
ArgumentPosition callbackSelfParameterPosition() { result.isLambdaSelf() }
|
||||
|
||||
/** Gets the synthesized data-flow call for `receiver`. */
|
||||
SummaryCall summaryDataFlowCall(SummaryNode receiver) { receiver = result.getReceiver() }
|
||||
@@ -215,6 +215,9 @@ string getParameterPosition(ParameterPosition pos) {
|
||||
pos.isSelf() and
|
||||
result = "self"
|
||||
or
|
||||
pos.isLambdaSelf() and
|
||||
result = "lambda-self"
|
||||
or
|
||||
pos.isBlock() and
|
||||
result = "block"
|
||||
or
|
||||
@@ -232,6 +235,8 @@ string getParameterPosition(ParameterPosition pos) {
|
||||
string getArgumentPosition(ArgumentPosition pos) {
|
||||
pos.isSelf() and result = "self"
|
||||
or
|
||||
pos.isLambdaSelf() and result = "lambda-self"
|
||||
or
|
||||
pos.isBlock() and result = "block"
|
||||
or
|
||||
exists(int i |
|
||||
@@ -372,6 +377,9 @@ ArgumentPosition parseParamBody(string s) {
|
||||
s = "self" and
|
||||
result.isSelf()
|
||||
or
|
||||
s = "lambda-self" and
|
||||
result.isLambdaSelf()
|
||||
or
|
||||
s = "block" and
|
||||
result.isBlock()
|
||||
or
|
||||
@@ -402,6 +410,9 @@ ParameterPosition parseArgBody(string s) {
|
||||
s = "self" and
|
||||
result.isSelf()
|
||||
or
|
||||
s = "lambda-self" and
|
||||
result.isLambdaSelf()
|
||||
or
|
||||
s = "block" and
|
||||
result.isBlock()
|
||||
or
|
||||
|
||||
@@ -363,97 +363,8 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate defReachesCallReadInOuterScope(
|
||||
Definition def, CallCfgNode call, LocalVariable v, Cfg::CfgScope scope
|
||||
) {
|
||||
exists(Cfg::BasicBlock bb, int i |
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
capturedCallRead(call, bb, i, v) and
|
||||
scope.getOuterCfgScope() = bb.getScope()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasCapturedEntryWrite(Definition entry, LocalVariable v, Cfg::CfgScope scope) {
|
||||
exists(Cfg::BasicBlock bb, int i |
|
||||
capturedEntryWrite(bb, i, v) and
|
||||
entry.definesAt(v, bb, i) and
|
||||
bb.getScope().getOuterCfgScope*() = scope
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(CallCfgNode call, Definition def, Definition entry) {
|
||||
exists(LocalVariable v, Cfg::CfgScope scope |
|
||||
defReachesCallReadInOuterScope(def, call, v, scope) and
|
||||
hasCapturedEntryWrite(entry, v, scope)
|
||||
|
|
||||
// If the read happens inside a block, we restrict to the call that
|
||||
// contains the block
|
||||
not scope instanceof Block
|
||||
or
|
||||
scope = call.getExpr().(MethodCall).getBlock()
|
||||
)
|
||||
}
|
||||
|
||||
private import codeql.ruby.dataflow.SSA
|
||||
|
||||
pragma[noinline]
|
||||
private predicate defReachesExitReadInInnerScope(
|
||||
Definition def, LocalVariable v, Cfg::CfgScope scope
|
||||
) {
|
||||
exists(Cfg::BasicBlock bb, int i |
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
capturedExitRead(bb, i, v) and
|
||||
scope = bb.getScope().getOuterCfgScope*()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasCapturedExitRead(
|
||||
Definition exit, CallCfgNode call, LocalVariable v, Cfg::CfgScope scope
|
||||
) {
|
||||
exists(Cfg::BasicBlock bb, int i |
|
||||
capturedCallWrite(call, bb, i, v) and
|
||||
exit.definesAt(v, bb, i) and
|
||||
bb.getScope() = scope.getOuterCfgScope()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is outgoing flow for a captured variable that is updated in a block.
|
||||
* ```rb
|
||||
* foo = 0
|
||||
* bar {
|
||||
* foo += 10
|
||||
* }
|
||||
* puts foo
|
||||
* ```
|
||||
*/
|
||||
cached
|
||||
predicate captureFlowOut(CallCfgNode call, Definition def, Definition exit) {
|
||||
exists(LocalVariable v, Cfg::CfgScope scope |
|
||||
defReachesExitReadInInnerScope(def, v, scope) and
|
||||
hasCapturedExitRead(exit, call, v, _)
|
||||
|
|
||||
// If the read happens inside a block, we restrict to the call that
|
||||
// contains the block
|
||||
not scope instanceof Block
|
||||
or
|
||||
scope = call.getExpr().(MethodCall).getBlock()
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
Definition phiHasInputFromBlock(PhiNode phi, Cfg::BasicBlock bb) {
|
||||
Impl::phiHasInputFromBlock(phi, result, bb)
|
||||
@@ -570,6 +481,8 @@ import Cached
|
||||
* Only intended for internal use.
|
||||
*/
|
||||
class DefinitionExt extends Impl::DefinitionExt {
|
||||
VariableReadAccessCfgNode getARead() { result = getARead(this) }
|
||||
|
||||
override string toString() { result = this.(Ssa::Definition).toString() }
|
||||
|
||||
/** Gets the location of this definition. */
|
||||
|
||||
@@ -273,39 +273,19 @@ module Sinatra {
|
||||
filter.getApp() = route.getApp() and
|
||||
// the filter applies to all routes
|
||||
not filter.hasPattern() and
|
||||
selfPostUpdate(pred, filter.getApp(), filter.getBody().asExpr().getExpr()) and
|
||||
blockCapturedSelfParameterNode(succ, route.getBody().asExpr().getExpr())
|
||||
blockPostUpdate(pred, filter.getBody()) and
|
||||
blockSelfParameterNode(succ, route.getBody().asExpr().getExpr())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is a post-update node for the `self` parameter of `app` in block `b`.
|
||||
*
|
||||
* In this example, `n` is the post-update node for `@foo = 1`.
|
||||
* ```rb
|
||||
* class MyApp < Sinatra::Base
|
||||
* before do
|
||||
* @foo = 1
|
||||
* end
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
private predicate selfPostUpdate(DataFlow::PostUpdateNode n, App app, Block b) {
|
||||
n.getPreUpdateNode().asExpr().getExpr() =
|
||||
any(SelfVariableAccess self |
|
||||
pragma[only_bind_into](b) = self.getEnclosingCallable() and
|
||||
self.getVariable().getDeclaringScope() = app.getADeclaration()
|
||||
)
|
||||
/** Holds if `n` is a post-update node for the block `b`. */
|
||||
private predicate blockPostUpdate(DataFlow::PostUpdateNode n, DataFlow::BlockNode b) {
|
||||
n.getPreUpdateNode() = b
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is a node representing the `self` parameter captured by block `b`.
|
||||
*/
|
||||
private predicate blockCapturedSelfParameterNode(DataFlow::Node n, Block b) {
|
||||
exists(Ssa::CapturedSelfDefinition d |
|
||||
n.(DataFlowPrivate::SsaDefinitionExtNode).getDefinitionExt() = d and
|
||||
d.getBasicBlock().getScope() = b
|
||||
)
|
||||
/** Holds if `n` is a `self` parameter belonging to block `b`. */
|
||||
private predicate blockSelfParameterNode(DataFlowPrivate::LambdaSelfParameterNode n, Block b) {
|
||||
n.getCallable() = b
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ predicate isExtraValidTokenArgumentInIdentifyingAccessPath(string name, string a
|
||||
or
|
||||
name = ["Argument", "Parameter"] and
|
||||
(
|
||||
argument = ["self", "block", "any", "any-named"]
|
||||
argument = ["self", "lambda-self", "block", "any", "any-named"]
|
||||
or
|
||||
argument.regexpMatch("\\w+:") // keyword argument
|
||||
)
|
||||
|
||||
@@ -6,7 +6,6 @@ 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.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import codeql.ruby.dataflow.internal.FlowSummaryImplSpecific as FlowSummaryImplSpecific
|
||||
private import codeql.ruby.dataflow.internal.AccessPathSyntax
|
||||
@@ -74,7 +73,7 @@ predicate simpleLocalFlowStep = DataFlowPrivate::localFlowStepTypeTracker/2;
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
|
||||
*/
|
||||
predicate jumpStep = DataFlowPrivate::jumpStepTypeTracker/2;
|
||||
predicate jumpStep = DataFlowPrivate::jumpStep/2;
|
||||
|
||||
/** Holds if there is direct flow from `param` to a return. */
|
||||
pragma[nomagic]
|
||||
@@ -180,6 +179,7 @@ private predicate argumentPositionMatch(
|
||||
) {
|
||||
exists(DataFlowDispatch::ArgumentPosition apos |
|
||||
arg.sourceArgumentOf(call, apos) and
|
||||
not apos.isLambdaSelf() and
|
||||
DataFlowDispatch::parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -450,10 +450,10 @@ edges
|
||||
| array_flow.rb:403:5:403:5 | a [element 2] | array_flow.rb:404:18:404:18 | a [element 2] |
|
||||
| array_flow.rb:403:16:403:25 | call to source | array_flow.rb:403:5:403:5 | a [element 2] |
|
||||
| array_flow.rb:404:5:404:5 | b [element 2] | array_flow.rb:408:10:408:10 | b [element 2] |
|
||||
| array_flow.rb:404:9:406:7 | __synth__0__1 | array_flow.rb:404:13:404:13 | x |
|
||||
| array_flow.rb:404:13:404:13 | x | array_flow.rb:405:14:405:14 | x |
|
||||
| array_flow.rb:404:13:404:13 | x | array_flow.rb:407:10:407:10 | x |
|
||||
| array_flow.rb:404:9:406:7 | [post] { ... } [captured x] | array_flow.rb:407:10:407:10 | x |
|
||||
| array_flow.rb:404:9:406:7 | __synth__0__1 | array_flow.rb:405:14:405:14 | x |
|
||||
| array_flow.rb:404:18:404:18 | a [element 2] | array_flow.rb:404:5:404:5 | b [element 2] |
|
||||
| array_flow.rb:404:18:404:18 | a [element 2] | array_flow.rb:404:9:406:7 | [post] { ... } [captured x] |
|
||||
| array_flow.rb:404:18:404:18 | a [element 2] | array_flow.rb:404:9:406:7 | __synth__0__1 |
|
||||
| array_flow.rb:408:10:408:10 | b [element 2] | array_flow.rb:408:10:408:13 | ...[...] |
|
||||
| array_flow.rb:412:5:412:5 | a [element 2] | array_flow.rb:413:5:413:5 | a [element 2] |
|
||||
@@ -2609,8 +2609,8 @@ nodes
|
||||
| array_flow.rb:403:5:403:5 | a [element 2] | semmle.label | a [element 2] |
|
||||
| array_flow.rb:403:16:403:25 | call to source | semmle.label | call to source |
|
||||
| array_flow.rb:404:5:404:5 | b [element 2] | semmle.label | b [element 2] |
|
||||
| array_flow.rb:404:9:406:7 | [post] { ... } [captured x] | semmle.label | [post] { ... } [captured x] |
|
||||
| array_flow.rb:404:9:406:7 | __synth__0__1 | semmle.label | __synth__0__1 |
|
||||
| array_flow.rb:404:13:404:13 | x | semmle.label | x |
|
||||
| array_flow.rb:404:18:404:18 | a [element 2] | semmle.label | a [element 2] |
|
||||
| array_flow.rb:405:14:405:14 | x | semmle.label | x |
|
||||
| array_flow.rb:407:10:407:10 | x | semmle.label | x |
|
||||
|
||||
@@ -32,7 +32,8 @@ edges
|
||||
| call_sensitivity.rb:66:20:66:20 | x | call_sensitivity.rb:67:24:67:24 | x |
|
||||
| call_sensitivity.rb:67:24:67:24 | x | call_sensitivity.rb:62:18:62:18 | y |
|
||||
| call_sensitivity.rb:70:30:70:30 | x | call_sensitivity.rb:71:10:71:10 | x |
|
||||
| call_sensitivity.rb:74:18:74:18 | y | call_sensitivity.rb:76:17:76:17 | y |
|
||||
| call_sensitivity.rb:74:18:74:18 | y | call_sensitivity.rb:75:20:77:7 | do ... end [captured y] |
|
||||
| call_sensitivity.rb:75:20:77:7 | do ... end [captured y] | call_sensitivity.rb:76:17:76:17 | y |
|
||||
| call_sensitivity.rb:76:17:76:17 | y | call_sensitivity.rb:50:15:50:15 | x |
|
||||
| call_sensitivity.rb:80:15:80:15 | x | call_sensitivity.rb:81:18:81:18 | x |
|
||||
| call_sensitivity.rb:81:18:81:18 | x | call_sensitivity.rb:50:15:50:15 | x |
|
||||
@@ -121,6 +122,7 @@ nodes
|
||||
| call_sensitivity.rb:70:30:70:30 | x | semmle.label | x |
|
||||
| call_sensitivity.rb:71:10:71:10 | x | semmle.label | x |
|
||||
| call_sensitivity.rb:74:18:74:18 | y | semmle.label | y |
|
||||
| call_sensitivity.rb:75:20:77:7 | do ... end [captured y] | semmle.label | do ... end [captured y] |
|
||||
| call_sensitivity.rb:76:17:76:17 | y | semmle.label | y |
|
||||
| call_sensitivity.rb:80:15:80:15 | x | semmle.label | x |
|
||||
| call_sensitivity.rb:81:18:81:18 | x | semmle.label | x |
|
||||
|
||||
@@ -1,49 +1,115 @@
|
||||
testFailures
|
||||
edges
|
||||
| captured_variables.rb:9:24:9:24 | x | captured_variables.rb:10:20:10:20 | x |
|
||||
| captured_variables.rb:9:24:9:24 | x | captured_variables.rb:10:10:10:23 | -> { ... } [captured x] |
|
||||
| captured_variables.rb:9:24:9:24 | x | captured_variables.rb:11:5:11:6 | fn [captured x] |
|
||||
| captured_variables.rb:10:5:10:6 | fn [captured x] | captured_variables.rb:11:5:11:6 | fn [captured x] |
|
||||
| captured_variables.rb:10:10:10:23 | -> { ... } [captured x] | captured_variables.rb:10:5:10:6 | fn [captured x] |
|
||||
| captured_variables.rb:11:5:11:6 | fn [captured x] | captured_variables.rb:10:20:10:20 | x |
|
||||
| captured_variables.rb:13:20:13:29 | call to taint | captured_variables.rb:9:24:9:24 | x |
|
||||
| captured_variables.rb:29:33:29:33 | x | captured_variables.rb:31:14:31:14 | x |
|
||||
| captured_variables.rb:15:28:15:28 | x | captured_variables.rb:16:5:18:5 | -> { ... } [captured x] |
|
||||
| captured_variables.rb:20:1:20:35 | ( ... ) [captured x] | captured_variables.rb:17:14:17:14 | x |
|
||||
| captured_variables.rb:20:2:20:34 | call to capture_escape_return1 [captured x] | captured_variables.rb:20:1:20:35 | ( ... ) [captured x] |
|
||||
| captured_variables.rb:20:25:20:34 | call to taint | captured_variables.rb:15:28:15:28 | x |
|
||||
| captured_variables.rb:20:25:20:34 | call to taint | captured_variables.rb:20:2:20:34 | call to capture_escape_return1 [captured x] |
|
||||
| captured_variables.rb:22:28:22:28 | x | captured_variables.rb:23:5:25:5 | -> { ... } [captured x] |
|
||||
| captured_variables.rb:27:25:27:57 | call to capture_escape_return2 [captured x] | captured_variables.rb:24:14:24:14 | x |
|
||||
| captured_variables.rb:27:48:27:57 | call to taint | captured_variables.rb:22:28:22:28 | x |
|
||||
| captured_variables.rb:27:48:27:57 | call to taint | captured_variables.rb:27:25:27:57 | call to capture_escape_return2 [captured x] |
|
||||
| captured_variables.rb:29:33:29:33 | x | captured_variables.rb:30:10:32:5 | -> { ... } [captured x] |
|
||||
| captured_variables.rb:29:33:29:33 | x | captured_variables.rb:33:29:33:30 | fn [captured x] |
|
||||
| captured_variables.rb:30:5:30:6 | fn [captured x] | captured_variables.rb:33:29:33:30 | fn [captured x] |
|
||||
| captured_variables.rb:30:10:32:5 | -> { ... } [captured x] | captured_variables.rb:30:5:30:6 | fn [captured x] |
|
||||
| captured_variables.rb:33:29:33:30 | fn [captured x] | captured_variables.rb:31:14:31:14 | x |
|
||||
| captured_variables.rb:35:29:35:38 | call to taint | captured_variables.rb:29:33:29:33 | x |
|
||||
| captured_variables.rb:40:31:40:31 | x | captured_variables.rb:42:14:42:14 | x |
|
||||
| captured_variables.rb:37:13:37:14 | fn [captured x] | captured_variables.rb:38:5:38:6 | fn [captured x] |
|
||||
| captured_variables.rb:38:5:38:6 | fn [captured x] | captured_variables.rb:42:14:42:14 | x |
|
||||
| captured_variables.rb:40:31:40:31 | x | captured_variables.rb:41:10:43:5 | -> { ... } [captured x] |
|
||||
| captured_variables.rb:40:31:40:31 | x | captured_variables.rb:44:13:44:14 | fn [captured x] |
|
||||
| captured_variables.rb:41:5:41:6 | fn [captured x] | captured_variables.rb:44:13:44:14 | fn [captured x] |
|
||||
| captured_variables.rb:41:10:43:5 | -> { ... } [captured x] | captured_variables.rb:41:5:41:6 | fn [captured x] |
|
||||
| captured_variables.rb:44:13:44:14 | fn [captured x] | captured_variables.rb:37:13:37:14 | fn [captured x] |
|
||||
| captured_variables.rb:46:27:46:36 | call to taint | captured_variables.rb:40:31:40:31 | x |
|
||||
| captured_variables.rb:48:1:48:1 | x | captured_variables.rb:50:10:50:10 | x |
|
||||
| captured_variables.rb:48:5:48:12 | call to taint | captured_variables.rb:48:1:48:1 | x |
|
||||
| captured_variables.rb:51:5:51:5 | x | captured_variables.rb:54:6:54:6 | x |
|
||||
| captured_variables.rb:51:9:51:16 | call to taint | captured_variables.rb:51:5:51:5 | x |
|
||||
| captured_variables.rb:48:5:48:12 | call to taint | captured_variables.rb:49:16:52:3 | do ... end [captured x] |
|
||||
| captured_variables.rb:48:5:48:12 | call to taint | captured_variables.rb:54:6:54:6 | x |
|
||||
| captured_variables.rb:49:16:52:3 | [post] do ... end [captured x] | captured_variables.rb:54:6:54:6 | x |
|
||||
| captured_variables.rb:49:16:52:3 | do ... end [captured x] | captured_variables.rb:50:10:50:10 | x |
|
||||
| captured_variables.rb:51:9:51:16 | call to taint | captured_variables.rb:49:16:52:3 | [post] do ... end [captured x] |
|
||||
| captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:18:58:18 | x |
|
||||
| captured_variables.rb:58:18:58:18 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] |
|
||||
| captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:16:61:21 | self [@field] |
|
||||
| captured_variables.rb:61:16:61:21 | @field | captured_variables.rb:61:9:61:21 | return |
|
||||
| captured_variables.rb:61:16:61:21 | self [@field] | captured_variables.rb:61:16:61:21 | @field |
|
||||
| captured_variables.rb:66:1:66:3 | [post] foo [@field] | captured_variables.rb:67:16:70:3 | do ... end [captured foo, @field] |
|
||||
| captured_variables.rb:66:1:66:3 | [post] foo [@field] | captured_variables.rb:72:6:72:8 | foo [@field] |
|
||||
| captured_variables.rb:66:15:66:22 | call to taint | captured_variables.rb:57:19:57:19 | x |
|
||||
| captured_variables.rb:66:15:66:22 | call to taint | captured_variables.rb:66:1:66:3 | [post] foo [@field] |
|
||||
| captured_variables.rb:66:15:66:22 | call to taint | instance_variables.rb:10:19:10:19 | x |
|
||||
| captured_variables.rb:67:16:70:3 | [post] do ... end [captured foo, @field] | captured_variables.rb:72:6:72:8 | foo [@field] |
|
||||
| captured_variables.rb:67:16:70:3 | do ... end [captured foo, @field] | captured_variables.rb:68:10:68:12 | foo [@field] |
|
||||
| captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] |
|
||||
| captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:68:10:68:22 | call to get_field |
|
||||
| captured_variables.rb:68:10:68:12 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] |
|
||||
| captured_variables.rb:69:5:69:7 | [post] foo [@field] | captured_variables.rb:67:16:70:3 | [post] do ... end [captured foo, @field] |
|
||||
| captured_variables.rb:69:19:69:26 | call to taint | captured_variables.rb:57:19:57:19 | x |
|
||||
| captured_variables.rb:69:19:69:26 | call to taint | captured_variables.rb:69:5:69:7 | [post] foo [@field] |
|
||||
| captured_variables.rb:69:19:69:26 | call to taint | instance_variables.rb:10:19:10:19 | x |
|
||||
| captured_variables.rb:72:6:72:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] |
|
||||
| captured_variables.rb:72:6:72:8 | foo [@field] | captured_variables.rb:72:6:72:18 | call to get_field |
|
||||
| captured_variables.rb:72:6:72:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] |
|
||||
| captured_variables.rb:85:1:85:1 | y | captured_variables.rb:87:10:87:10 | y |
|
||||
| captured_variables.rb:85:5:85:12 | call to taint | captured_variables.rb:85:1:85:1 | y |
|
||||
| captured_variables.rb:88:5:88:5 | y | captured_variables.rb:87:10:87:10 | y |
|
||||
| captured_variables.rb:88:5:88:5 | y | captured_variables.rb:91:6:91:6 | y |
|
||||
| captured_variables.rb:88:9:88:16 | call to taint | captured_variables.rb:88:5:88:5 | y |
|
||||
| captured_variables.rb:78:20:80:7 | [post] do ... end [captured foo, @field] | captured_variables.rb:83:6:83:8 | foo [@field] |
|
||||
| captured_variables.rb:79:9:79:11 | [post] foo [@field] | captured_variables.rb:78:20:80:7 | [post] do ... end [captured foo, @field] |
|
||||
| captured_variables.rb:79:23:79:30 | call to taint | captured_variables.rb:57:19:57:19 | x |
|
||||
| captured_variables.rb:79:23:79:30 | call to taint | captured_variables.rb:79:9:79:11 | [post] foo [@field] |
|
||||
| captured_variables.rb:79:23:79:30 | call to taint | instance_variables.rb:10:19:10:19 | x |
|
||||
| captured_variables.rb:83:6:83:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] |
|
||||
| captured_variables.rb:83:6:83:8 | foo [@field] | captured_variables.rb:83:6:83:18 | call to get_field |
|
||||
| captured_variables.rb:83:6:83:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] |
|
||||
| captured_variables.rb:85:5:85:12 | call to taint | captured_variables.rb:86:6:89:1 | -> { ... } [captured y] |
|
||||
| captured_variables.rb:85:5:85:12 | call to taint | captured_variables.rb:90:1:90:2 | fn [captured y] |
|
||||
| captured_variables.rb:85:5:85:12 | call to taint | captured_variables.rb:91:6:91:6 | y |
|
||||
| captured_variables.rb:86:1:86:2 | fn [captured y] | captured_variables.rb:90:1:90:2 | fn [captured y] |
|
||||
| captured_variables.rb:86:6:89:1 | -> { ... } [captured y] | captured_variables.rb:86:1:86:2 | fn [captured y] |
|
||||
| captured_variables.rb:88:9:88:16 | call to taint | captured_variables.rb:90:1:90:2 | [post] fn [captured y] |
|
||||
| captured_variables.rb:90:1:90:2 | [post] fn [captured y] | captured_variables.rb:91:6:91:6 | y |
|
||||
| captured_variables.rb:90:1:90:2 | fn [captured y] | captured_variables.rb:87:10:87:10 | y |
|
||||
| captured_variables.rb:93:17:93:17 | x | captured_variables.rb:94:5:96:5 | -> { ... } [captured x] |
|
||||
| captured_variables.rb:98:1:98:21 | call to capture_arg [captured x] | captured_variables.rb:95:14:95:14 | x |
|
||||
| captured_variables.rb:98:13:98:20 | call to taint | captured_variables.rb:93:17:93:17 | x |
|
||||
| captured_variables.rb:98:13:98:20 | call to taint | captured_variables.rb:98:1:98:21 | call to capture_arg [captured x] |
|
||||
| captured_variables.rb:100:21:100:21 | x | captured_variables.rb:101:11:101:11 | x |
|
||||
| captured_variables.rb:101:11:101:11 | x | captured_variables.rb:104:31:104:31 | x |
|
||||
| captured_variables.rb:104:17:104:24 | call to taint | captured_variables.rb:100:21:100:21 | x |
|
||||
| captured_variables.rb:104:31:104:31 | x | captured_variables.rb:105:10:105:10 | x |
|
||||
| captured_variables.rb:109:5:109:5 | x | captured_variables.rb:112:18:112:18 | x |
|
||||
| captured_variables.rb:109:9:109:17 | call to taint | captured_variables.rb:109:5:109:5 | x |
|
||||
| captured_variables.rb:113:13:113:13 | x | captured_variables.rb:112:18:112:18 | x |
|
||||
| captured_variables.rb:113:13:113:13 | x | captured_variables.rb:118:10:118:10 | x |
|
||||
| captured_variables.rb:113:17:113:25 | call to taint | captured_variables.rb:113:13:113:13 | x |
|
||||
| captured_variables.rb:109:9:109:17 | call to taint | captured_variables.rb:110:14:116:5 | -> { ... } [captured x] |
|
||||
| captured_variables.rb:109:9:109:17 | call to taint | captured_variables.rb:117:5:117:10 | middle [captured x] |
|
||||
| captured_variables.rb:109:9:109:17 | call to taint | captured_variables.rb:118:10:118:10 | x |
|
||||
| captured_variables.rb:110:5:110:10 | middle [captured x] | captured_variables.rb:117:5:117:10 | middle [captured x] |
|
||||
| captured_variables.rb:110:14:116:5 | -> { ... } [captured x] | captured_variables.rb:110:5:110:10 | middle [captured x] |
|
||||
| captured_variables.rb:111:9:111:13 | inner [captured x] | captured_variables.rb:115:9:115:13 | inner [captured x] |
|
||||
| captured_variables.rb:111:17:114:9 | -> { ... } [captured x] | captured_variables.rb:111:9:111:13 | inner [captured x] |
|
||||
| captured_variables.rb:113:17:113:25 | call to taint | captured_variables.rb:115:9:115:13 | [post] inner [captured x] |
|
||||
| captured_variables.rb:115:9:115:13 | [post] inner [captured x] | captured_variables.rb:117:5:117:10 | [post] middle [captured x] |
|
||||
| captured_variables.rb:115:9:115:13 | inner [captured x] | captured_variables.rb:112:18:112:18 | x |
|
||||
| captured_variables.rb:117:5:117:10 | [post] middle [captured x] | captured_variables.rb:118:10:118:10 | x |
|
||||
| captured_variables.rb:117:5:117:10 | middle [captured x] | captured_variables.rb:111:17:114:9 | -> { ... } [captured x] |
|
||||
| captured_variables.rb:117:5:117:10 | middle [captured x] | captured_variables.rb:115:9:115:13 | inner [captured x] |
|
||||
| captured_variables.rb:147:5:147:6 | [post] self [@x] | captured_variables.rb:153:14:155:7 | do ... end [captured self, @x] |
|
||||
| captured_variables.rb:147:10:147:18 | call to taint | captured_variables.rb:147:5:147:6 | [post] self [@x] |
|
||||
| captured_variables.rb:149:5:151:7 | &block [captured self, @x] | captured_variables.rb:154:14:154:15 | self [@x] |
|
||||
| captured_variables.rb:153:14:155:7 | do ... end [captured self, @x] | captured_variables.rb:149:5:151:7 | &block [captured self, @x] |
|
||||
| captured_variables.rb:154:14:154:15 | self [@x] | captured_variables.rb:154:14:154:15 | @x |
|
||||
| captured_variables.rb:160:9:160:10 | [post] self [@x] | captured_variables.rb:174:1:174:24 | call to new [@x] |
|
||||
| captured_variables.rb:160:14:160:22 | call to taint | captured_variables.rb:160:9:160:10 | [post] self [@x] |
|
||||
| captured_variables.rb:167:5:171:7 | self in baz [@x] | captured_variables.rb:169:18:169:19 | self [@x] |
|
||||
| captured_variables.rb:163:5:165:7 | &block [captured self, @x] | captured_variables.rb:169:18:169:19 | self [@x] |
|
||||
| captured_variables.rb:167:5:171:7 | self in baz [@x] | captured_variables.rb:168:18:170:11 | do ... end [captured self, @x] |
|
||||
| captured_variables.rb:168:18:170:11 | do ... end [captured self, @x] | captured_variables.rb:163:5:165:7 | &block [captured self, @x] |
|
||||
| captured_variables.rb:169:18:169:19 | self [@x] | captured_variables.rb:169:18:169:19 | @x |
|
||||
| captured_variables.rb:174:1:174:24 | call to new [@x] | captured_variables.rb:167:5:171:7 | self in baz [@x] |
|
||||
| captured_variables.rb:178:9:178:10 | [post] self [@x] | captured_variables.rb:193:1:193:1 | [post] c [@x] |
|
||||
| captured_variables.rb:178:14:178:22 | call to taint | captured_variables.rb:178:9:178:10 | [post] self [@x] |
|
||||
| captured_variables.rb:185:5:189:7 | self in baz [@x] | captured_variables.rb:187:18:187:19 | self [@x] |
|
||||
| captured_variables.rb:181:5:183:7 | &block [captured self, @x] | captured_variables.rb:187:18:187:19 | self [@x] |
|
||||
| captured_variables.rb:185:5:189:7 | self in baz [@x] | captured_variables.rb:186:18:188:11 | do ... end [captured self, @x] |
|
||||
| captured_variables.rb:186:18:188:11 | do ... end [captured self, @x] | captured_variables.rb:181:5:183:7 | &block [captured self, @x] |
|
||||
| captured_variables.rb:187:18:187:19 | self [@x] | captured_variables.rb:187:18:187:19 | @x |
|
||||
| captured_variables.rb:193:1:193:1 | [post] c [@x] | captured_variables.rb:194:1:194:1 | c [@x] |
|
||||
| captured_variables.rb:194:1:194:1 | c [@x] | captured_variables.rb:185:5:189:7 | self in baz [@x] |
|
||||
@@ -188,18 +254,40 @@ edges
|
||||
| instance_variables.rb:121:7:121:24 | call to new | instance_variables.rb:121:1:121:3 | bar |
|
||||
nodes
|
||||
| captured_variables.rb:9:24:9:24 | x | semmle.label | x |
|
||||
| captured_variables.rb:10:5:10:6 | fn [captured x] | semmle.label | fn [captured x] |
|
||||
| captured_variables.rb:10:10:10:23 | -> { ... } [captured x] | semmle.label | -> { ... } [captured x] |
|
||||
| captured_variables.rb:10:20:10:20 | x | semmle.label | x |
|
||||
| captured_variables.rb:11:5:11:6 | fn [captured x] | semmle.label | fn [captured x] |
|
||||
| captured_variables.rb:13:20:13:29 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:15:28:15:28 | x | semmle.label | x |
|
||||
| captured_variables.rb:16:5:18:5 | -> { ... } [captured x] | semmle.label | -> { ... } [captured x] |
|
||||
| captured_variables.rb:17:14:17:14 | x | semmle.label | x |
|
||||
| captured_variables.rb:20:1:20:35 | ( ... ) [captured x] | semmle.label | ( ... ) [captured x] |
|
||||
| captured_variables.rb:20:2:20:34 | call to capture_escape_return1 [captured x] | semmle.label | call to capture_escape_return1 [captured x] |
|
||||
| captured_variables.rb:20:25:20:34 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:22:28:22:28 | x | semmle.label | x |
|
||||
| captured_variables.rb:23:5:25:5 | -> { ... } [captured x] | semmle.label | -> { ... } [captured x] |
|
||||
| captured_variables.rb:24:14:24:14 | x | semmle.label | x |
|
||||
| captured_variables.rb:27:25:27:57 | call to capture_escape_return2 [captured x] | semmle.label | call to capture_escape_return2 [captured x] |
|
||||
| captured_variables.rb:27:48:27:57 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:29:33:29:33 | x | semmle.label | x |
|
||||
| captured_variables.rb:30:5:30:6 | fn [captured x] | semmle.label | fn [captured x] |
|
||||
| captured_variables.rb:30:10:32:5 | -> { ... } [captured x] | semmle.label | -> { ... } [captured x] |
|
||||
| captured_variables.rb:31:14:31:14 | x | semmle.label | x |
|
||||
| captured_variables.rb:33:29:33:30 | fn [captured x] | semmle.label | fn [captured x] |
|
||||
| captured_variables.rb:35:29:35:38 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:37:13:37:14 | fn [captured x] | semmle.label | fn [captured x] |
|
||||
| captured_variables.rb:38:5:38:6 | fn [captured x] | semmle.label | fn [captured x] |
|
||||
| captured_variables.rb:40:31:40:31 | x | semmle.label | x |
|
||||
| captured_variables.rb:41:5:41:6 | fn [captured x] | semmle.label | fn [captured x] |
|
||||
| captured_variables.rb:41:10:43:5 | -> { ... } [captured x] | semmle.label | -> { ... } [captured x] |
|
||||
| captured_variables.rb:42:14:42:14 | x | semmle.label | x |
|
||||
| captured_variables.rb:44:13:44:14 | fn [captured x] | semmle.label | fn [captured x] |
|
||||
| captured_variables.rb:46:27:46:36 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:48:1:48:1 | x | semmle.label | x |
|
||||
| captured_variables.rb:48:5:48:12 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:49:16:52:3 | [post] do ... end [captured x] | semmle.label | [post] do ... end [captured x] |
|
||||
| captured_variables.rb:49:16:52:3 | do ... end [captured x] | semmle.label | do ... end [captured x] |
|
||||
| captured_variables.rb:50:10:50:10 | x | semmle.label | x |
|
||||
| captured_variables.rb:51:5:51:5 | x | semmle.label | x |
|
||||
| captured_variables.rb:51:9:51:16 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:54:6:54:6 | x | semmle.label | x |
|
||||
| captured_variables.rb:57:19:57:19 | x | semmle.label | x |
|
||||
@@ -211,34 +299,68 @@ nodes
|
||||
| captured_variables.rb:61:16:61:21 | self [@field] | semmle.label | self [@field] |
|
||||
| captured_variables.rb:66:1:66:3 | [post] foo [@field] | semmle.label | [post] foo [@field] |
|
||||
| captured_variables.rb:66:15:66:22 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:67:16:70:3 | [post] do ... end [captured foo, @field] | semmle.label | [post] do ... end [captured foo, @field] |
|
||||
| captured_variables.rb:67:16:70:3 | do ... end [captured foo, @field] | semmle.label | do ... end [captured foo, @field] |
|
||||
| captured_variables.rb:68:10:68:12 | foo [@field] | semmle.label | foo [@field] |
|
||||
| captured_variables.rb:68:10:68:22 | call to get_field | semmle.label | call to get_field |
|
||||
| captured_variables.rb:69:5:69:7 | [post] foo [@field] | semmle.label | [post] foo [@field] |
|
||||
| captured_variables.rb:69:19:69:26 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:72:6:72:8 | foo [@field] | semmle.label | foo [@field] |
|
||||
| captured_variables.rb:72:6:72:18 | call to get_field | semmle.label | call to get_field |
|
||||
| captured_variables.rb:85:1:85:1 | y | semmle.label | y |
|
||||
| captured_variables.rb:78:20:80:7 | [post] do ... end [captured foo, @field] | semmle.label | [post] do ... end [captured foo, @field] |
|
||||
| captured_variables.rb:79:9:79:11 | [post] foo [@field] | semmle.label | [post] foo [@field] |
|
||||
| captured_variables.rb:79:23:79:30 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:83:6:83:8 | foo [@field] | semmle.label | foo [@field] |
|
||||
| captured_variables.rb:83:6:83:18 | call to get_field | semmle.label | call to get_field |
|
||||
| captured_variables.rb:85:5:85:12 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:86:1:86:2 | fn [captured y] | semmle.label | fn [captured y] |
|
||||
| captured_variables.rb:86:6:89:1 | -> { ... } [captured y] | semmle.label | -> { ... } [captured y] |
|
||||
| captured_variables.rb:87:10:87:10 | y | semmle.label | y |
|
||||
| captured_variables.rb:88:5:88:5 | y | semmle.label | y |
|
||||
| captured_variables.rb:88:9:88:16 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:90:1:90:2 | [post] fn [captured y] | semmle.label | [post] fn [captured y] |
|
||||
| captured_variables.rb:90:1:90:2 | fn [captured y] | semmle.label | fn [captured y] |
|
||||
| captured_variables.rb:91:6:91:6 | y | semmle.label | y |
|
||||
| captured_variables.rb:93:17:93:17 | x | semmle.label | x |
|
||||
| captured_variables.rb:94:5:96:5 | -> { ... } [captured x] | semmle.label | -> { ... } [captured x] |
|
||||
| captured_variables.rb:95:14:95:14 | x | semmle.label | x |
|
||||
| captured_variables.rb:98:1:98:21 | call to capture_arg [captured x] | semmle.label | call to capture_arg [captured x] |
|
||||
| captured_variables.rb:98:13:98:20 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:100:21:100:21 | x | semmle.label | x |
|
||||
| captured_variables.rb:101:11:101:11 | x | semmle.label | x |
|
||||
| captured_variables.rb:104:17:104:24 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:104:31:104:31 | x | semmle.label | x |
|
||||
| captured_variables.rb:105:10:105:10 | x | semmle.label | x |
|
||||
| captured_variables.rb:109:5:109:5 | x | semmle.label | x |
|
||||
| captured_variables.rb:109:9:109:17 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:110:5:110:10 | middle [captured x] | semmle.label | middle [captured x] |
|
||||
| captured_variables.rb:110:14:116:5 | -> { ... } [captured x] | semmle.label | -> { ... } [captured x] |
|
||||
| captured_variables.rb:111:9:111:13 | inner [captured x] | semmle.label | inner [captured x] |
|
||||
| captured_variables.rb:111:17:114:9 | -> { ... } [captured x] | semmle.label | -> { ... } [captured x] |
|
||||
| captured_variables.rb:112:18:112:18 | x | semmle.label | x |
|
||||
| captured_variables.rb:113:13:113:13 | x | semmle.label | x |
|
||||
| captured_variables.rb:113:17:113:25 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:115:9:115:13 | [post] inner [captured x] | semmle.label | [post] inner [captured x] |
|
||||
| captured_variables.rb:115:9:115:13 | inner [captured x] | semmle.label | inner [captured x] |
|
||||
| captured_variables.rb:117:5:117:10 | [post] middle [captured x] | semmle.label | [post] middle [captured x] |
|
||||
| captured_variables.rb:117:5:117:10 | middle [captured x] | semmle.label | middle [captured x] |
|
||||
| captured_variables.rb:118:10:118:10 | x | semmle.label | x |
|
||||
| captured_variables.rb:147:5:147:6 | [post] self [@x] | semmle.label | [post] self [@x] |
|
||||
| captured_variables.rb:147:10:147:18 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:149:5:151:7 | &block [captured self, @x] | semmle.label | &block [captured self, @x] |
|
||||
| captured_variables.rb:153:14:155:7 | do ... end [captured self, @x] | semmle.label | do ... end [captured self, @x] |
|
||||
| captured_variables.rb:154:14:154:15 | @x | semmle.label | @x |
|
||||
| captured_variables.rb:154:14:154:15 | self [@x] | semmle.label | self [@x] |
|
||||
| captured_variables.rb:160:9:160:10 | [post] self [@x] | semmle.label | [post] self [@x] |
|
||||
| captured_variables.rb:160:14:160:22 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:163:5:165:7 | &block [captured self, @x] | semmle.label | &block [captured self, @x] |
|
||||
| captured_variables.rb:167:5:171:7 | self in baz [@x] | semmle.label | self in baz [@x] |
|
||||
| captured_variables.rb:168:18:170:11 | do ... end [captured self, @x] | semmle.label | do ... end [captured self, @x] |
|
||||
| captured_variables.rb:169:18:169:19 | @x | semmle.label | @x |
|
||||
| captured_variables.rb:169:18:169:19 | self [@x] | semmle.label | self [@x] |
|
||||
| captured_variables.rb:174:1:174:24 | call to new [@x] | semmle.label | call to new [@x] |
|
||||
| captured_variables.rb:178:9:178:10 | [post] self [@x] | semmle.label | [post] self [@x] |
|
||||
| captured_variables.rb:178:14:178:22 | call to taint | semmle.label | call to taint |
|
||||
| captured_variables.rb:181:5:183:7 | &block [captured self, @x] | semmle.label | &block [captured self, @x] |
|
||||
| captured_variables.rb:185:5:189:7 | self in baz [@x] | semmle.label | self in baz [@x] |
|
||||
| captured_variables.rb:186:18:188:11 | do ... end [captured self, @x] | semmle.label | do ... end [captured self, @x] |
|
||||
| captured_variables.rb:187:18:187:19 | @x | semmle.label | @x |
|
||||
| captured_variables.rb:187:18:187:19 | self [@x] | semmle.label | self [@x] |
|
||||
| captured_variables.rb:193:1:193:1 | [post] c [@x] | semmle.label | [post] c [@x] |
|
||||
@@ -348,10 +470,21 @@ nodes
|
||||
| instance_variables.rb:121:7:121:24 | call to new | semmle.label | call to new |
|
||||
| instance_variables.rb:122:6:122:8 | bar | semmle.label | bar |
|
||||
subpaths
|
||||
| captured_variables.rb:20:25:20:34 | call to taint | captured_variables.rb:15:28:15:28 | x | captured_variables.rb:16:5:18:5 | -> { ... } [captured x] | captured_variables.rb:20:2:20:34 | call to capture_escape_return1 [captured x] |
|
||||
| captured_variables.rb:27:48:27:57 | call to taint | captured_variables.rb:22:28:22:28 | x | captured_variables.rb:23:5:25:5 | -> { ... } [captured x] | captured_variables.rb:27:25:27:57 | call to capture_escape_return2 [captured x] |
|
||||
| captured_variables.rb:66:15:66:22 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | captured_variables.rb:66:1:66:3 | [post] foo [@field] |
|
||||
| captured_variables.rb:66:15:66:22 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | captured_variables.rb:66:1:66:3 | [post] foo [@field] |
|
||||
| captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | captured_variables.rb:68:10:68:22 | call to get_field |
|
||||
| captured_variables.rb:68:10:68:12 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | captured_variables.rb:68:10:68:22 | call to get_field |
|
||||
| captured_variables.rb:69:19:69:26 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | captured_variables.rb:69:5:69:7 | [post] foo [@field] |
|
||||
| captured_variables.rb:69:19:69:26 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | captured_variables.rb:69:5:69:7 | [post] foo [@field] |
|
||||
| captured_variables.rb:72:6:72:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | captured_variables.rb:72:6:72:18 | call to get_field |
|
||||
| captured_variables.rb:72:6:72:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | captured_variables.rb:72:6:72:18 | call to get_field |
|
||||
| captured_variables.rb:79:23:79:30 | call to taint | captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | captured_variables.rb:79:9:79:11 | [post] foo [@field] |
|
||||
| captured_variables.rb:79:23:79:30 | call to taint | instance_variables.rb:10:19:10:19 | x | instance_variables.rb:11:9:11:14 | [post] self [@field] | captured_variables.rb:79:9:79:11 | [post] foo [@field] |
|
||||
| captured_variables.rb:83:6:83:8 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | captured_variables.rb:83:6:83:18 | call to get_field |
|
||||
| captured_variables.rb:83:6:83:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | captured_variables.rb:83:6:83:18 | call to get_field |
|
||||
| captured_variables.rb:98:13:98:20 | call to taint | captured_variables.rb:93:17:93:17 | x | captured_variables.rb:94:5:96:5 | -> { ... } [captured x] | captured_variables.rb:98:1:98:21 | call to capture_arg [captured x] |
|
||||
| instance_variables.rb:28:20:28:24 | field | instance_variables.rb:22:20:22:24 | field | instance_variables.rb:23:9:23:14 | [post] self [@field] | instance_variables.rb:28:9:28:25 | [post] self [@field] |
|
||||
| instance_variables.rb:33:13:33:13 | x | instance_variables.rb:22:20:22:24 | field | instance_variables.rb:23:9:23:14 | [post] self [@field] | instance_variables.rb:33:9:33:14 | call to new [@field] |
|
||||
| instance_variables.rb:36:10:36:23 | call to new [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:9:61:21 | return | instance_variables.rb:36:10:36:33 | call to get_field |
|
||||
@@ -416,18 +549,26 @@ subpaths
|
||||
| instance_variables.rb:120:6:120:10 | foo16 [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | instance_variables.rb:14:9:14:21 | return | instance_variables.rb:120:6:120:20 | call to get_field |
|
||||
#select
|
||||
| captured_variables.rb:10:20:10:20 | x | captured_variables.rb:13:20:13:29 | call to taint | captured_variables.rb:10:20:10:20 | x | $@ | captured_variables.rb:13:20:13:29 | call to taint | call to taint |
|
||||
| captured_variables.rb:17:14:17:14 | x | captured_variables.rb:20:25:20:34 | call to taint | captured_variables.rb:17:14:17:14 | x | $@ | captured_variables.rb:20:25:20:34 | call to taint | call to taint |
|
||||
| captured_variables.rb:24:14:24:14 | x | captured_variables.rb:27:48:27:57 | call to taint | captured_variables.rb:24:14:24:14 | x | $@ | captured_variables.rb:27:48:27:57 | call to taint | call to taint |
|
||||
| captured_variables.rb:31:14:31:14 | x | captured_variables.rb:35:29:35:38 | call to taint | captured_variables.rb:31:14:31:14 | x | $@ | captured_variables.rb:35:29:35:38 | call to taint | call to taint |
|
||||
| captured_variables.rb:42:14:42:14 | x | captured_variables.rb:46:27:46:36 | call to taint | captured_variables.rb:42:14:42:14 | x | $@ | captured_variables.rb:46:27:46:36 | call to taint | call to taint |
|
||||
| captured_variables.rb:50:10:50:10 | x | captured_variables.rb:48:5:48:12 | call to taint | captured_variables.rb:50:10:50:10 | x | $@ | captured_variables.rb:48:5:48:12 | call to taint | call to taint |
|
||||
| captured_variables.rb:54:6:54:6 | x | captured_variables.rb:48:5:48:12 | call to taint | captured_variables.rb:54:6:54:6 | x | $@ | captured_variables.rb:48:5:48:12 | call to taint | call to taint |
|
||||
| captured_variables.rb:54:6:54:6 | x | captured_variables.rb:51:9:51:16 | call to taint | captured_variables.rb:54:6:54:6 | x | $@ | captured_variables.rb:51:9:51:16 | call to taint | call to taint |
|
||||
| captured_variables.rb:68:10:68:22 | call to get_field | captured_variables.rb:66:15:66:22 | call to taint | captured_variables.rb:68:10:68:22 | call to get_field | $@ | captured_variables.rb:66:15:66:22 | call to taint | call to taint |
|
||||
| captured_variables.rb:72:6:72:18 | call to get_field | captured_variables.rb:66:15:66:22 | call to taint | captured_variables.rb:72:6:72:18 | call to get_field | $@ | captured_variables.rb:66:15:66:22 | call to taint | call to taint |
|
||||
| captured_variables.rb:72:6:72:18 | call to get_field | captured_variables.rb:69:19:69:26 | call to taint | captured_variables.rb:72:6:72:18 | call to get_field | $@ | captured_variables.rb:69:19:69:26 | call to taint | call to taint |
|
||||
| captured_variables.rb:83:6:83:18 | call to get_field | captured_variables.rb:79:23:79:30 | call to taint | captured_variables.rb:83:6:83:18 | call to get_field | $@ | captured_variables.rb:79:23:79:30 | call to taint | call to taint |
|
||||
| captured_variables.rb:87:10:87:10 | y | captured_variables.rb:85:5:85:12 | call to taint | captured_variables.rb:87:10:87:10 | y | $@ | captured_variables.rb:85:5:85:12 | call to taint | call to taint |
|
||||
| captured_variables.rb:87:10:87:10 | y | captured_variables.rb:88:9:88:16 | call to taint | captured_variables.rb:87:10:87:10 | y | $@ | captured_variables.rb:88:9:88:16 | call to taint | call to taint |
|
||||
| captured_variables.rb:91:6:91:6 | y | captured_variables.rb:85:5:85:12 | call to taint | captured_variables.rb:91:6:91:6 | y | $@ | captured_variables.rb:85:5:85:12 | call to taint | call to taint |
|
||||
| captured_variables.rb:91:6:91:6 | y | captured_variables.rb:88:9:88:16 | call to taint | captured_variables.rb:91:6:91:6 | y | $@ | captured_variables.rb:88:9:88:16 | call to taint | call to taint |
|
||||
| captured_variables.rb:95:14:95:14 | x | captured_variables.rb:98:13:98:20 | call to taint | captured_variables.rb:95:14:95:14 | x | $@ | captured_variables.rb:98:13:98:20 | call to taint | call to taint |
|
||||
| captured_variables.rb:105:10:105:10 | x | captured_variables.rb:104:17:104:24 | call to taint | captured_variables.rb:105:10:105:10 | x | $@ | captured_variables.rb:104:17:104:24 | call to taint | call to taint |
|
||||
| captured_variables.rb:112:18:112:18 | x | captured_variables.rb:109:9:109:17 | call to taint | captured_variables.rb:112:18:112:18 | x | $@ | captured_variables.rb:109:9:109:17 | call to taint | call to taint |
|
||||
| captured_variables.rb:112:18:112:18 | x | captured_variables.rb:113:17:113:25 | call to taint | captured_variables.rb:112:18:112:18 | x | $@ | captured_variables.rb:113:17:113:25 | call to taint | call to taint |
|
||||
| captured_variables.rb:118:10:118:10 | x | captured_variables.rb:109:9:109:17 | call to taint | captured_variables.rb:118:10:118:10 | x | $@ | captured_variables.rb:109:9:109:17 | call to taint | call to taint |
|
||||
| captured_variables.rb:118:10:118:10 | x | captured_variables.rb:113:17:113:25 | call to taint | captured_variables.rb:118:10:118:10 | x | $@ | captured_variables.rb:113:17:113:25 | call to taint | call to taint |
|
||||
| captured_variables.rb:154:14:154:15 | @x | captured_variables.rb:147:10:147:18 | call to taint | captured_variables.rb:154:14:154:15 | @x | $@ | captured_variables.rb:147:10:147:18 | call to taint | call to taint |
|
||||
| captured_variables.rb:169:18:169:19 | @x | captured_variables.rb:160:14:160:22 | call to taint | captured_variables.rb:169:18:169:19 | @x | $@ | captured_variables.rb:160:14:160:22 | call to taint | call to taint |
|
||||
| captured_variables.rb:187:18:187:19 | @x | captured_variables.rb:178:14:178:22 | call to taint | captured_variables.rb:187:18:187:19 | @x | $@ | captured_variables.rb:178:14:178:22 | call to taint | call to taint |
|
||||
| instance_variables.rb:20:10:20:13 | @foo | instance_variables.rb:19:12:19:21 | call to taint | instance_variables.rb:20:10:20:13 | @foo | $@ | instance_variables.rb:19:12:19:21 | call to taint | call to taint |
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
testFailures
|
||||
| captured_variables.rb:17:14:17:14 | x | Fixed missing result:hasValueFlow=1.2 |
|
||||
| captured_variables.rb:24:14:24:14 | x | Fixed missing result:hasValueFlow=1.3 |
|
||||
| captured_variables.rb:50:10:50:10 | x | Fixed missing result:hasValueFlow=2 |
|
||||
| captured_variables.rb:54:6:54:6 | x | Unexpected result: hasValueFlow=1 |
|
||||
| captured_variables.rb:72:21:72:75 | # $ MISSING: hasValueFlow=4 $ SPURIOUS: hasValueFlow=3 | Fixed spurious result:hasValueFlow=3 |
|
||||
| captured_variables.rb:91:6:91:6 | y | Unexpected result: hasValueFlow=6 |
|
||||
| captured_variables.rb:95:14:95:14 | x | Fixed missing result:hasValueFlow=8 |
|
||||
| captured_variables.rb:118:10:118:10 | x | Unexpected result: hasValueFlow=10 |
|
||||
| captured_variables.rb:68:25:68:68 | # $ hasValueFlow=3 $ MISSING: hasValueFlow=4 | Missing result:hasValueFlow=3 |
|
||||
| captured_variables.rb:72:21:72:66 | # $ hasValueFlow=4 $ SPURIOUS: hasValueFlow=3 | Fixed spurious result:hasValueFlow=3 |
|
||||
| captured_variables.rb:72:21:72:66 | # $ hasValueFlow=4 $ SPURIOUS: hasValueFlow=3 | Missing result:hasValueFlow=4 |
|
||||
| captured_variables.rb:83:21:83:38 | # $ hasValueFlow=5 | Missing result:hasValueFlow=5 |
|
||||
| captured_variables.rb:87:10:87:10 | y | Unexpected result: hasValueFlow=7 |
|
||||
| captured_variables.rb:112:18:112:18 | x | Unexpected result: hasValueFlow=11 |
|
||||
| captured_variables.rb:126:14:126:14 | x | Fixed missing result:hasValueFlow=12 |
|
||||
| captured_variables.rb:154:17:154:35 | # $ hasValueFlow=13 | Missing result:hasValueFlow=13 |
|
||||
| instance_variables.rb:20:16:20:33 | # $ hasValueFlow=7 | Missing result:hasValueFlow=7 |
|
||||
| instance_variables.rb:36:36:36:54 | # $ hasValueFlow=34 | Missing result:hasValueFlow=34 |
|
||||
| instance_variables.rb:39:36:39:54 | # $ hasValueFlow=35 | Missing result:hasValueFlow=35 |
|
||||
|
||||
@@ -14,14 +14,14 @@ capture_local_call taint(1.1)
|
||||
|
||||
def capture_escape_return1 x
|
||||
-> {
|
||||
sink(x) # $ MISSING: hasValueFlow=1.2
|
||||
sink(x) # $ hasValueFlow=1.2
|
||||
}
|
||||
end
|
||||
(capture_escape_return1 taint(1.2)).call
|
||||
|
||||
def capture_escape_return2 x
|
||||
-> {
|
||||
sink(x) # $ MISSING: hasValueFlow=1.3
|
||||
sink(x) # $ hasValueFlow=1.3
|
||||
}
|
||||
end
|
||||
Something.unknownMethod(capture_escape_return2 taint(1.3))
|
||||
@@ -51,7 +51,7 @@ x = taint(1)
|
||||
x = taint(2)
|
||||
end
|
||||
|
||||
sink x # $ hasValueFlow=2
|
||||
sink x # $ hasValueFlow=2 $ SPURIOUS: hasValueFlow=1
|
||||
|
||||
class Foo
|
||||
def set_field x
|
||||
@@ -65,11 +65,11 @@ end
|
||||
foo = Foo.new
|
||||
foo.set_field(taint(3))
|
||||
[1, 2, 3].each do |i|
|
||||
sink(foo.get_field) # $ MISSING: hasValueFlow=3 $ MISSING: hasValueFlow=4
|
||||
sink(foo.get_field) # $ hasValueFlow=3 $ MISSING: hasValueFlow=4
|
||||
foo.set_field(taint(4))
|
||||
end
|
||||
|
||||
sink(foo.get_field) # $ MISSING: hasValueFlow=4 $ SPURIOUS: hasValueFlow=3
|
||||
sink(foo.get_field) # $ hasValueFlow=4 $ SPURIOUS: hasValueFlow=3
|
||||
|
||||
foo = Foo.new
|
||||
if (rand() < 0) then
|
||||
@@ -80,19 +80,19 @@ else
|
||||
end
|
||||
end
|
||||
|
||||
sink(foo.get_field) # $ MISSING: hasValueFlow=5
|
||||
sink(foo.get_field) # $ hasValueFlow=5
|
||||
|
||||
y = taint(6)
|
||||
fn = -> {
|
||||
sink(y) # $ hasValueFlow=6 $ SPURIOUS: hasValueFlow=7
|
||||
sink(y) # $ hasValueFlow=6
|
||||
y = taint(7)
|
||||
}
|
||||
fn.call
|
||||
sink(y) # $ hasValueFlow=7
|
||||
sink(y) # $ hasValueFlow=7 $ SPURIOUS: hasValueFlow=6
|
||||
|
||||
def capture_arg x
|
||||
-> {
|
||||
sink x # $ MISSING: hasValueFlow=8
|
||||
sink x # $ hasValueFlow=8
|
||||
}
|
||||
end
|
||||
capture_arg(taint(8)).call
|
||||
@@ -109,13 +109,13 @@ def capture_nested
|
||||
x = taint(10)
|
||||
middle = -> {
|
||||
inner = -> {
|
||||
sink x # $ hasValueFlow=10 $ SPURIOUS: hasValueFlow=11
|
||||
sink x # $ hasValueFlow=10
|
||||
x = taint(11)
|
||||
}
|
||||
inner.call
|
||||
}
|
||||
middle.call
|
||||
sink x # $ hasValueFlow=11
|
||||
sink x # $ hasValueFlow=11 $ SPURIOUS: hasValueFlow=10
|
||||
end
|
||||
capture_nested
|
||||
|
||||
@@ -151,7 +151,7 @@ module CaptureModuleSelf
|
||||
end
|
||||
|
||||
self.foo do
|
||||
sink @x # $ MISSING: hasValueFlow=13
|
||||
sink @x # $ hasValueFlow=13
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,59 +1,57 @@
|
||||
testFailures
|
||||
edges
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:2:6:2:12 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:2:6:2:12 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:4:24:4:30 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:4:24:4:30 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:16:36:16:42 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:16:36:16:42 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:20:25:20:31 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:26:31:26:37 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:30:24:30:30 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:31:27:31:33 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:34:16:34:22 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:34:16:34:22 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:35:16:35:22 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:35:16:35:22 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:36:21:36:27 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:36:21:36:27 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:37:36:37:42 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:37:36:37:42 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:51:24:51:30 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:56:22:56:28 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:57:17:57:23 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:59:27:59:33 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:63:32:63:38 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:65:23:65:29 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:122:16:122:22 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:128:14:128:20 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:131:16:131:22 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:131:16:131:22 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:132:21:132:27 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:132:21:132:27 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:135:26:135:32 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:135:26:135:32 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:137:23:137:29 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:137:23:137:29 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:140:19:140:25 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:140:19:140:25 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:141:19:141:25 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:141:19:141:25 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:145:26:145:32 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:145:26:145:32 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:147:16:147:22 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:147:16:147:22 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:150:39:150:45 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:150:39:150:45 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:154:20:154:26 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:154:20:154:26 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:155:28:155:34 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:155:28:155:34 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:156:27:156:33 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:156:27:156:33 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:158:15:158:21 | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | summaries.rb:158:15:158:21 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:1:1:1:7 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:1:1:1:7 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:2:6:2:12 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:2:6:2:12 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:4:24:4:30 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:4:24:4:30 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:16:36:16:42 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:16:36:16:42 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:20:25:20:31 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:26:31:26:37 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:30:24:30:30 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:31:27:31:33 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:51:24:51:30 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:56:22:56:28 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:57:17:57:23 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:59:27:59:33 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:63:32:63:38 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:65:23:65:29 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:122:16:122:22 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:128:14:128:20 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:157:14:160:3 | do ... end [captured tainted] |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:157:14:160:3 | do ... end [captured tainted] |
|
||||
| summaries.rb:1:20:1:36 | call to source | summaries.rb:1:11:1:36 | call to identity |
|
||||
| summaries.rb:1:20:1:36 | call to source | summaries.rb:1:11:1:36 | call to identity |
|
||||
| summaries.rb:4:1:4:8 | tainted2 | summaries.rb:9:6:9:13 | tainted2 |
|
||||
@@ -242,6 +240,7 @@ edges
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:154:20:154:26 | tainted |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:155:28:155:34 | tainted |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:156:27:156:33 | tainted |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:157:14:160:3 | do ... end [captured tainted] |
|
||||
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:16:122:22 | [post] tainted |
|
||||
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:25:122:25 | [post] y |
|
||||
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:33:122:33 | [post] z |
|
||||
@@ -249,9 +248,9 @@ edges
|
||||
| summaries.rb:122:33:122:33 | [post] z | summaries.rb:125:6:125:6 | z |
|
||||
| summaries.rb:128:1:128:1 | [post] x | summaries.rb:129:6:129:6 | x |
|
||||
| summaries.rb:128:14:128:20 | tainted | summaries.rb:128:1:128:1 | [post] x |
|
||||
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | summaries.rb:158:15:158:21 | tainted |
|
||||
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | summaries.rb:158:15:158:21 | tainted |
|
||||
nodes
|
||||
| summaries.rb:1:1:1:7 | tainted | semmle.label | tainted |
|
||||
| summaries.rb:1:1:1:7 | tainted | semmle.label | tainted |
|
||||
| summaries.rb:1:11:1:36 | call to identity | semmle.label | call to identity |
|
||||
| summaries.rb:1:11:1:36 | call to identity | semmle.label | call to identity |
|
||||
| summaries.rb:1:20:1:36 | call to source | semmle.label | call to source |
|
||||
@@ -491,6 +490,8 @@ nodes
|
||||
| summaries.rb:155:28:155:34 | tainted | semmle.label | tainted |
|
||||
| summaries.rb:156:27:156:33 | tainted | semmle.label | tainted |
|
||||
| summaries.rb:156:27:156:33 | tainted | semmle.label | tainted |
|
||||
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | semmle.label | do ... end [captured tainted] |
|
||||
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | semmle.label | do ... end [captured tainted] |
|
||||
| summaries.rb:158:15:158:21 | tainted | semmle.label | tainted |
|
||||
| summaries.rb:158:15:158:21 | tainted | semmle.label | tainted |
|
||||
| summaries.rb:163:20:163:36 | call to source | semmle.label | call to source |
|
||||
|
||||
@@ -43,51 +43,43 @@ filterPatterns
|
||||
| app.rb:106:3:108:5 | call to before | app.rb:106:10:106:23 | "/protected/*" |
|
||||
| app.rb:111:3:113:5 | call to after | app.rb:111:9:111:23 | "/create/:slug" |
|
||||
additionalFlowSteps
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:2:22:4:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:10:21:13:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:15:23:18:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:24:26:26:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:37:16:42:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:44:53:46:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:56:32:58:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:60:48:62:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:74:11:77:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:79:11:82:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:89:16:92:5 | <captured entry> self |
|
||||
| app.rb:85:5:85:9 | [post] self | app.rb:94:15:96:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:2:22:4:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:10:21:13:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:15:23:18:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:24:26:26:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:37:16:42:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:44:53:46:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:56:32:58:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:60:48:62:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:74:11:77:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:79:11:82:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:89:16:92:5 | <captured entry> self |
|
||||
| app.rb:86:5:86:11 | [post] self | app.rb:94:15:96:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:2:22:4:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:10:21:13:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:15:23:18:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:24:26:26:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:37:16:42:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:44:53:46:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:56:32:58:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:60:48:62:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:74:11:77:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:79:11:82:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:89:16:92:5 | <captured entry> self |
|
||||
| app.rb:103:5:103:9 | [post] self | app.rb:94:15:96:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:2:22:4:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:10:21:13:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:15:23:18:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:24:26:26:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:37:16:42:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:44:53:46:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:56:32:58:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:60:48:62:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:74:11:77:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:79:11:82:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:89:16:92:5 | <captured entry> self |
|
||||
| app.rb:103:13:103:22 | [post] self | app.rb:94:15:96:5 | <captured entry> self |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:2:22:4:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:6:24:8:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:10:21:13:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:15:23:18:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:20:23:22:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:24:26:26:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:28:26:31:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:33:25:35:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:37:16:42:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:44:53:46:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:48:14:50:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:52:37:54:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:56:32:58:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:60:48:62:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:66:41:68:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:70:20:72:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:74:11:77:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:79:11:82:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:89:16:92:5 | lambda self in do ... end |
|
||||
| app.rb:84:10:87:5 | [post] do ... end | app.rb:94:15:96:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:2:22:4:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:6:24:8:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:10:21:13:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:15:23:18:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:20:23:22:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:24:26:26:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:28:26:31:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:33:25:35:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:37:16:42:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:44:53:46:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:48:14:50:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:52:37:54:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:56:32:58:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:60:48:62:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:66:41:68:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:70:20:72:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:74:11:77:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:79:11:82:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:89:16:92:5 | lambda self in do ... end |
|
||||
| app.rb:102:10:104:5 | [post] do ... end | app.rb:94:15:96:5 | lambda self in do ... end |
|
||||
|
||||
@@ -7,15 +7,15 @@ edges
|
||||
| ErbInjection.rb:8:5:8:12 | bad_text | ErbInjection.rb:19:20:19:27 | bad_text |
|
||||
| ErbInjection.rb:8:16:11:14 | ... % ... | ErbInjection.rb:8:5:8:12 | bad_text |
|
||||
| ErbInjection.rb:11:11:11:14 | name | ErbInjection.rb:8:16:11:14 | ... % ... |
|
||||
| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:8:5:8:12 | bad_text |
|
||||
| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:11:11:11:14 | name |
|
||||
| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:17:5:17:13 | bad2_text |
|
||||
| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] |
|
||||
| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] |
|
||||
| SlimInjection.rb:5:12:5:17 | call to params | SlimInjection.rb:5:12:5:24 | ...[...] |
|
||||
| SlimInjection.rb:5:12:5:24 | ...[...] | SlimInjection.rb:5:5:5:8 | name |
|
||||
| SlimInjection.rb:8:5:8:12 | bad_text | SlimInjection.rb:14:25:14:32 | bad_text |
|
||||
| SlimInjection.rb:8:16:11:14 | ... % ... | SlimInjection.rb:8:5:8:12 | bad_text |
|
||||
| SlimInjection.rb:8:16:11:14 | ... % ... | SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] |
|
||||
| SlimInjection.rb:11:11:11:14 | name | SlimInjection.rb:8:16:11:14 | ... % ... |
|
||||
| SlimInjection.rb:17:5:17:13 | bad2_text | SlimInjection.rb:23:25:23:33 | bad2_text |
|
||||
| SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | SlimInjection.rb:14:25:14:32 | bad_text |
|
||||
| SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] | SlimInjection.rb:23:25:23:33 | bad2_text |
|
||||
nodes
|
||||
| ErbInjection.rb:5:5:5:8 | name | semmle.label | name |
|
||||
| ErbInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
|
||||
@@ -28,11 +28,11 @@ nodes
|
||||
| SlimInjection.rb:5:5:5:8 | name | semmle.label | name |
|
||||
| SlimInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
|
||||
| SlimInjection.rb:5:12:5:24 | ...[...] | semmle.label | ...[...] |
|
||||
| SlimInjection.rb:8:5:8:12 | bad_text | semmle.label | bad_text |
|
||||
| SlimInjection.rb:8:16:11:14 | ... % ... | semmle.label | ... % ... |
|
||||
| SlimInjection.rb:11:11:11:14 | name | semmle.label | name |
|
||||
| SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | semmle.label | { ... } [captured bad_text] |
|
||||
| SlimInjection.rb:14:25:14:32 | bad_text | semmle.label | bad_text |
|
||||
| SlimInjection.rb:17:5:17:13 | bad2_text | semmle.label | bad2_text |
|
||||
| SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] | semmle.label | { ... } [captured bad2_text] |
|
||||
| SlimInjection.rb:23:25:23:33 | bad2_text | semmle.label | bad2_text |
|
||||
subpaths
|
||||
#select
|
||||
|
||||
@@ -5,7 +5,9 @@ edges
|
||||
| ArchiveApiPathTraversal.rb:10:11:10:23 | ...[...] | ArchiveApiPathTraversal.rb:67:13:67:16 | file |
|
||||
| ArchiveApiPathTraversal.rb:15:9:15:14 | call to params | ArchiveApiPathTraversal.rb:15:9:15:25 | ...[...] |
|
||||
| ArchiveApiPathTraversal.rb:15:9:15:25 | ...[...] | ArchiveApiPathTraversal.rb:75:11:75:18 | filename |
|
||||
| ArchiveApiPathTraversal.rb:49:17:49:27 | destination | ArchiveApiPathTraversal.rb:52:38:52:48 | destination |
|
||||
| ArchiveApiPathTraversal.rb:49:17:49:27 | destination | ArchiveApiPathTraversal.rb:50:36:64:7 | do ... end [captured destination] |
|
||||
| ArchiveApiPathTraversal.rb:50:36:64:7 | do ... end [captured destination] | ArchiveApiPathTraversal.rb:51:16:63:9 | do ... end [captured destination] |
|
||||
| ArchiveApiPathTraversal.rb:51:16:63:9 | do ... end [captured destination] | ArchiveApiPathTraversal.rb:52:38:52:48 | destination |
|
||||
| ArchiveApiPathTraversal.rb:52:9:52:24 | destination_file | ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file |
|
||||
| ArchiveApiPathTraversal.rb:52:28:52:67 | call to join | ArchiveApiPathTraversal.rb:52:9:52:24 | destination_file |
|
||||
| ArchiveApiPathTraversal.rb:52:38:52:48 | destination | ArchiveApiPathTraversal.rb:52:28:52:67 | call to join |
|
||||
@@ -72,6 +74,8 @@ nodes
|
||||
| ArchiveApiPathTraversal.rb:15:9:15:14 | call to params | semmle.label | call to params |
|
||||
| ArchiveApiPathTraversal.rb:15:9:15:25 | ...[...] | semmle.label | ...[...] |
|
||||
| ArchiveApiPathTraversal.rb:49:17:49:27 | destination | semmle.label | destination |
|
||||
| ArchiveApiPathTraversal.rb:50:36:64:7 | do ... end [captured destination] | semmle.label | do ... end [captured destination] |
|
||||
| ArchiveApiPathTraversal.rb:51:16:63:9 | do ... end [captured destination] | semmle.label | do ... end [captured destination] |
|
||||
| ArchiveApiPathTraversal.rb:52:9:52:24 | destination_file | semmle.label | destination_file |
|
||||
| ArchiveApiPathTraversal.rb:52:28:52:67 | call to join | semmle.label | call to join |
|
||||
| ArchiveApiPathTraversal.rb:52:38:52:48 | destination | semmle.label | destination |
|
||||
|
||||
@@ -4,14 +4,16 @@ edges
|
||||
| app/controllers/users_controller.rb:15:5:15:15 | unsanitized | app/controllers/users_controller.rb:23:20:23:30 | unsanitized |
|
||||
| app/controllers/users_controller.rb:15:19:15:24 | call to params | app/controllers/users_controller.rb:15:19:15:30 | ...[...] |
|
||||
| app/controllers/users_controller.rb:15:19:15:30 | ...[...] | app/controllers/users_controller.rb:15:5:15:15 | unsanitized |
|
||||
| app/controllers/users_controller.rb:23:5:23:16 | unsanitized2 | app/controllers/users_controller.rb:25:7:25:18 | unsanitized2 |
|
||||
| app/controllers/users_controller.rb:23:5:23:16 | unsanitized2 | app/controllers/users_controller.rb:27:16:27:39 | ... + ... |
|
||||
| app/controllers/users_controller.rb:23:20:23:30 | unsanitized | app/controllers/users_controller.rb:23:20:23:44 | call to sub |
|
||||
| app/controllers/users_controller.rb:23:20:23:44 | call to sub | app/controllers/users_controller.rb:23:5:23:16 | unsanitized2 |
|
||||
| app/controllers/users_controller.rb:33:5:33:15 | unsanitized | app/controllers/users_controller.rb:34:33:34:43 | unsanitized |
|
||||
| app/controllers/users_controller.rb:33:5:33:15 | unsanitized | app/controllers/users_controller.rb:35:33:35:55 | ... + ... |
|
||||
| app/controllers/users_controller.rb:23:20:23:44 | call to sub | app/controllers/users_controller.rb:24:18:26:7 | do ... end [captured unsanitized2] |
|
||||
| app/controllers/users_controller.rb:23:20:23:44 | call to sub | app/controllers/users_controller.rb:27:16:27:39 | ... + ... |
|
||||
| app/controllers/users_controller.rb:24:18:26:7 | do ... end [captured unsanitized2] | app/controllers/users_controller.rb:25:7:25:18 | unsanitized2 |
|
||||
| app/controllers/users_controller.rb:33:19:33:25 | call to cookies | app/controllers/users_controller.rb:33:19:33:31 | ...[...] |
|
||||
| app/controllers/users_controller.rb:33:19:33:31 | ...[...] | app/controllers/users_controller.rb:33:5:33:15 | unsanitized |
|
||||
| app/controllers/users_controller.rb:33:19:33:31 | ...[...] | app/controllers/users_controller.rb:34:31:34:45 | { ... } [captured unsanitized] |
|
||||
| app/controllers/users_controller.rb:33:19:33:31 | ...[...] | app/controllers/users_controller.rb:35:31:35:57 | { ... } [captured unsanitized] |
|
||||
| app/controllers/users_controller.rb:34:31:34:45 | { ... } [captured unsanitized] | app/controllers/users_controller.rb:34:33:34:43 | unsanitized |
|
||||
| app/controllers/users_controller.rb:35:31:35:57 | { ... } [captured unsanitized] | app/controllers/users_controller.rb:35:45:35:55 | unsanitized |
|
||||
| app/controllers/users_controller.rb:35:45:35:55 | unsanitized | app/controllers/users_controller.rb:35:33:35:55 | ... + ... |
|
||||
| app/controllers/users_controller.rb:49:19:49:24 | call to params | app/controllers/users_controller.rb:49:19:49:30 | ...[...] |
|
||||
nodes
|
||||
| app/controllers/users_controller.rb:15:5:15:15 | unsanitized | semmle.label | unsanitized |
|
||||
@@ -19,16 +21,18 @@ nodes
|
||||
| app/controllers/users_controller.rb:15:19:15:30 | ...[...] | semmle.label | ...[...] |
|
||||
| app/controllers/users_controller.rb:16:19:16:29 | unsanitized | semmle.label | unsanitized |
|
||||
| app/controllers/users_controller.rb:17:19:17:41 | ... + ... | semmle.label | ... + ... |
|
||||
| app/controllers/users_controller.rb:23:5:23:16 | unsanitized2 | semmle.label | unsanitized2 |
|
||||
| app/controllers/users_controller.rb:23:20:23:30 | unsanitized | semmle.label | unsanitized |
|
||||
| app/controllers/users_controller.rb:23:20:23:44 | call to sub | semmle.label | call to sub |
|
||||
| app/controllers/users_controller.rb:24:18:26:7 | do ... end [captured unsanitized2] | semmle.label | do ... end [captured unsanitized2] |
|
||||
| app/controllers/users_controller.rb:25:7:25:18 | unsanitized2 | semmle.label | unsanitized2 |
|
||||
| app/controllers/users_controller.rb:27:16:27:39 | ... + ... | semmle.label | ... + ... |
|
||||
| app/controllers/users_controller.rb:33:5:33:15 | unsanitized | semmle.label | unsanitized |
|
||||
| app/controllers/users_controller.rb:33:19:33:25 | call to cookies | semmle.label | call to cookies |
|
||||
| app/controllers/users_controller.rb:33:19:33:31 | ...[...] | semmle.label | ...[...] |
|
||||
| app/controllers/users_controller.rb:34:31:34:45 | { ... } [captured unsanitized] | semmle.label | { ... } [captured unsanitized] |
|
||||
| app/controllers/users_controller.rb:34:33:34:43 | unsanitized | semmle.label | unsanitized |
|
||||
| app/controllers/users_controller.rb:35:31:35:57 | { ... } [captured unsanitized] | semmle.label | { ... } [captured unsanitized] |
|
||||
| app/controllers/users_controller.rb:35:33:35:55 | ... + ... | semmle.label | ... + ... |
|
||||
| app/controllers/users_controller.rb:35:45:35:55 | unsanitized | semmle.label | unsanitized |
|
||||
| app/controllers/users_controller.rb:49:19:49:24 | call to params | semmle.label | call to params |
|
||||
| app/controllers/users_controller.rb:49:19:49:30 | ...[...] | semmle.label | ...[...] |
|
||||
subpaths
|
||||
|
||||
Reference in New Issue
Block a user