Merge branch 'main' into criemen/pytest-ruby

This commit is contained in:
Cornelius Riemenschneider
2024-08-06 16:41:23 +02:00
committed by GitHub
595 changed files with 19516 additions and 612 deletions

View File

@@ -0,0 +1,11 @@
private import codeql.ruby.CFG
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
pragma[nomagic]
predicate guardControlsBlock(CfgNodes::AstCfgNode guard, BasicBlock bb, boolean branch) {
exists(ConditionBlock conditionBlock, SuccessorTypes::ConditionalSuccessor s |
guard = conditionBlock.getLastNode() and
s.getValue() = branch and
conditionBlock.controls(bb, s)
)
}

View File

@@ -202,8 +202,17 @@ module Ssa {
final VariableWriteAccessCfgNode getWriteAccess() { result = write }
/**
* Holds if this SSA definition represents a direct assignment of `value`
* to the underlying variable.
* Holds if this SSA definition assigns `value` to the underlying variable.
*
* This is either a direct assignment, `x = value`, or an assignment via
* simple pattern matching
*
* ```rb
* case value
* in Foo => x then ...
* in y => then ...
* end
* ```
*/
predicate assigns(CfgNodes::ExprCfgNode value) {
exists(CfgNodes::ExprNodes::AssignExprCfgNode a, BasicBlock bb, int i |
@@ -211,6 +220,14 @@ module Ssa {
a = bb.getNode(i) and
value = a.getRhs()
)
or
exists(CfgNodes::ExprNodes::CaseExprCfgNode case, CfgNodes::AstCfgNode pattern |
case.getValue() = value and
pattern = case.getBranch(_).(CfgNodes::ExprNodes::InClauseCfgNode).getPattern()
|
this.getWriteAccess() =
[pattern, pattern.(CfgNodes::ExprNodes::AsPatternCfgNode).getVariableAccess()]
)
}
final override string toString() { result = write.toString() }

View File

@@ -1073,8 +1073,7 @@ private module TrackSingletonMethodOnInstanceInput implements CallGraphConstruct
singletonMethodOnInstance(_, _, nodeFromPreExpr.getExpr())
)
|
nodeFromPreExpr =
LocalFlow::getParameterDefNode(p.getParameter()).getDefinitionExt().getARead()
nodeFromPreExpr = getParameterDef(p.getParameter()).getARead()
or
nodeFromPreExpr = p.(SelfParameterNodeImpl).getSelfDefinition().getARead()
)

View File

@@ -72,134 +72,48 @@ CfgNodes::ExprCfgNode getAPostUpdateNodeForArg(Argument arg) {
not exists(getALastEvalNode(result))
}
/** An SSA definition into which another SSA definition may flow. */
class SsaInputDefinitionExt extends SsaImpl::DefinitionExt {
SsaInputDefinitionExt() {
this instanceof Ssa::PhiNode
/** Gets the SSA definition node corresponding to parameter `p`. */
pragma[nomagic]
SsaImpl::DefinitionExt getParameterDef(NamedParameter p) {
exists(BasicBlock bb, int i |
bb.getNode(i).getAstNode() = p.getDefiningAccess() and
result.definesAt(_, bb, i, _)
)
}
/** Provides logic related to SSA. */
module SsaFlow {
private module Impl = SsaImpl::DataFlowIntegration;
private ParameterNodeImpl toParameterNode(SsaImpl::ParameterExt p) {
result = TNormalParameterNode(p.asParameter())
or
this instanceof SsaImpl::PhiReadNode
result = TSelfMethodParameterNode(p.asMethodSelf())
or
result = TSelfToplevelParameterNode(p.asToplevelSelf())
}
predicate hasInputFromBlock(SsaImpl::DefinitionExt def, BasicBlock bb, int i, BasicBlock input) {
SsaImpl::lastRefBeforeRedefExt(def, bb, i, input, this)
Impl::Node asNode(Node n) {
n = TSsaNode(result)
or
result.(Impl::ExprNode).getExpr() = n.asExpr()
or
result.(Impl::ExprPostUpdateNode).getExpr() = n.(PostUpdateNode).getPreUpdateNode().asExpr()
or
n = toParameterNode(result.(Impl::ParameterNode).getParameter())
}
predicate localFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo, boolean isUseStep) {
Impl::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo), isUseStep)
}
predicate localMustFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
Impl::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
}
}
/** Provides predicates related to local data flow. */
module LocalFlow {
/**
* Holds if `nodeFrom` is a node for SSA definition `def`, which can reach `next`.
*/
pragma[nomagic]
private predicate localFlowSsaInputFromDef(
SsaDefinitionExtNode nodeFrom, SsaImpl::DefinitionExt def, SsaInputNode nodeTo
) {
exists(BasicBlock bb, int i, BasicBlock input, SsaInputDefinitionExt next |
next.hasInputFromBlock(def, bb, i, input) and
def = nodeFrom.getDefinitionExt() and
def.definesAt(_, bb, i, _) and
nodeTo = TSsaInputNode(next, input)
)
}
/**
* Holds if `nodeFrom` is a last read of SSA definition `def`, which
* can reach `nodeTo`.
*/
pragma[nomagic]
predicate localFlowSsaInputFromRead(SsaImpl::DefinitionExt def, Node nodeFrom, SsaInputNode nodeTo) {
exists(
BasicBlock bb, int i, CfgNodes::ExprCfgNode exprFrom, BasicBlock input,
SsaInputDefinitionExt next
|
next.hasInputFromBlock(def, bb, i, input) and
exprFrom = bb.getNode(i) and
exprFrom.getExpr() instanceof VariableReadAccess and
exprFrom = [nodeFrom.asExpr(), nodeFrom.(PostUpdateNodeImpl).getPreUpdateNode().asExpr()] and
nodeTo = TSsaInputNode(next, input)
)
}
/** 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
result.getDefinitionExt().definesAt(_, bb, i, _)
)
}
/**
* Holds if `nodeFrom` is a parameter node, and `nodeTo` is a corresponding SSA node.
*/
pragma[nomagic]
predicate localFlowSsaParamInput(ParameterNodeImpl nodeFrom, SsaDefinitionExtNode nodeTo) {
nodeTo = getParameterDefNode(nodeFrom.getParameter())
or
nodeTo.getDefinitionExt() = nodeFrom.(SelfParameterNodeImpl).getSelfDefinition()
}
/**
* Holds if there is a local use-use flow step from `nodeFrom` to `nodeTo`
* involving SSA definition `def`.
*/
predicate localSsaFlowStepUseUse(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
SsaImpl::adjacentReadPairExt(def, nodeFrom.asExpr(), nodeTo.asExpr())
}
/**
* Holds if SSA definition `def` assigns `value` to the underlying variable.
*
* This is either a direct assignment, `x = value`, or an assignment via
* simple pattern matching
*
* ```rb
* case value
* in Foo => x then ...
* in y => then ...
* end
* ```
*/
predicate ssaDefAssigns(Ssa::WriteDefinition def, CfgNodes::ExprCfgNode value) {
def.assigns(value)
or
exists(CfgNodes::ExprNodes::CaseExprCfgNode case, CfgNodes::AstCfgNode pattern |
case.getValue() = value and
pattern = case.getBranch(_).(CfgNodes::ExprNodes::InClauseCfgNode).getPattern()
|
def.getWriteAccess() = pattern
or
def.getWriteAccess() = pattern.(CfgNodes::ExprNodes::AsPatternCfgNode).getVariableAccess()
)
}
/**
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
* SSA definition `def`.
*/
pragma[nomagic]
predicate localSsaFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
// Flow from assignment into SSA definition
ssaDefAssigns(def, nodeFrom.asExpr()) and
nodeTo.(SsaDefinitionExtNode).getDefinitionExt() = def
or
// Flow from SSA definition to first read
def = nodeFrom.(SsaDefinitionExtNode).getDefinitionExt() and
SsaImpl::firstReadExt(def, nodeTo.asExpr())
or
// Flow from post-update read to next read
localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNodeImpl).getPreUpdateNode(), nodeTo)
or
// Flow into phi (read) SSA definition node from def
localFlowSsaInputFromDef(nodeFrom, def, nodeTo)
or
nodeTo.(SsaDefinitionExtNode).getDefinitionExt() = def and
def = nodeFrom.(SsaInputNode).getDefinitionExt()
or
localFlowSsaParamInput(nodeFrom, nodeTo) and
def = nodeTo.(SsaDefinitionExtNode).getDefinitionExt()
}
pragma[nomagic]
predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::BlockArgumentCfgNode).getValue()
@@ -240,7 +154,7 @@ module LocalFlow {
p.(KeywordParameter).getDefaultValue() = nodeFrom.asExpr().getExpr()
)
or
nodeTo.(BlockArgumentNode).getParameterNode(true) = nodeFrom
nodeTo.(ImplicitBlockArgumentNode).getParameterNode(true) = nodeFrom
}
predicate flowSummaryLocalStep(
@@ -253,21 +167,13 @@ module LocalFlow {
}
predicate localMustFlowStep(Node node1, Node node2) {
LocalFlow::localFlowSsaParamInput(node1, node2)
or
exists(SsaImpl::Definition def |
def.(Ssa::WriteDefinition).assigns(node1.asExpr()) and
node2.(SsaDefinitionExtNode).getDefinitionExt() = def
or
def = node1.(SsaDefinitionExtNode).getDefinitionExt() and
node2.asExpr() = SsaImpl::getARead(def)
)
SsaFlow::localMustFlowStep(_, node1, node2)
or
node1.asExpr() = node2.asExpr().(CfgNodes::ExprNodes::AssignExprCfgNode).getRhs()
or
node1.asExpr() = node2.asExpr().(CfgNodes::ExprNodes::BlockArgumentCfgNode).getValue()
or
node1 = node2.(BlockArgumentNode).getParameterNode(true)
node1 = node2.(ImplicitBlockArgumentNode).getParameterNode(true)
or
node1 =
unique(FlowSummaryNode n1 |
@@ -347,7 +253,7 @@ module VariableCapture {
or
exists(Ssa::Definition def |
def.getARead() = e2 and
LocalFlow::ssaDefAssigns(def.getAnUltimateDefinition(), e1)
def.getAnUltimateDefinition().(Ssa::WriteDefinition).assigns(e1)
)
}
@@ -538,23 +444,14 @@ private module Cached {
newtype TNode =
TExprNode(CfgNodes::ExprCfgNode n) or
TReturningNode(CfgNodes::ReturningCfgNode n) { exists(n.getReturnedValueNode()) } or
TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) or
TSsaInputNode(SsaInputDefinitionExt def, BasicBlock input) {
def.hasInputFromBlock(_, _, _, input)
} or
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
TCapturedVariableNode(VariableCapture::CapturedVariable v) or
TNormalParameterNode(Parameter p) {
p instanceof SimpleParameter or
p instanceof OptionalParameter or
p instanceof KeywordParameter or
p instanceof HashSplatParameter or
p instanceof SplatParameter
} or
TNormalParameterNode(SsaImpl::NormalParameter p) or
TSelfMethodParameterNode(MethodBase m) or
TSelfToplevelParameterNode(Toplevel t) or
TLambdaSelfReferenceNode(Callable c) { lambdaCreationExpr(_, _, c) } or
TBlockParameterNode(MethodBase m) or
TBlockArgumentNode(CfgNodes::ExprNodes::CallCfgNode yield) {
TImplicitBlockParameterNode(MethodBase m) { not m.getAParameter() instanceof BlockParameter } or
TImplicitBlockArgumentNode(CfgNodes::ExprNodes::CallCfgNode yield) {
yield = any(BlockParameterNode b).getAYieldCall()
} or
TSynthHashSplatParameterNode(DataFlowCallable c) {
@@ -600,7 +497,7 @@ private module Cached {
class TSelfParameterNode = TSelfMethodParameterNode or TSelfToplevelParameterNode;
class TSourceParameterNode =
TNormalParameterNode or TBlockParameterNode or TSelfParameterNode or
TNormalParameterNode or TImplicitBlockParameterNode or TSelfParameterNode or
TSynthHashSplatParameterNode or TSynthSplatParameterNode;
cached
@@ -618,16 +515,13 @@ private module Cached {
(
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
or
exists(SsaImpl::DefinitionExt def |
exists(SsaImpl::DefinitionExt def, boolean isUseStep |
SsaFlow::localFlowStep(def, nodeFrom, nodeTo, isUseStep) and
// captured variables are handled by the shared `VariableCapture` library
not def instanceof VariableCapture::CapturedSsaDefinitionExt
|
LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo)
isUseStep = false
or
LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
or
LocalFlow::localFlowSsaInputFromRead(def, nodeFrom, nodeTo) and
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
)
or
@@ -643,11 +537,7 @@ private module Cached {
predicate localFlowStepImpl(Node nodeFrom, Node nodeTo) {
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
or
LocalFlow::localSsaFlowStep(_, nodeFrom, nodeTo)
or
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
or
LocalFlow::localFlowSsaInputFromRead(_, nodeFrom, nodeTo)
SsaFlow::localFlowStep(_, nodeFrom, nodeTo, _)
or
// Simple flow through library code is included in the exposed local
// step relation, even though flow is technically inter-procedural
@@ -661,11 +551,7 @@ private module Cached {
predicate localFlowStepTypeTracker(Node nodeFrom, Node nodeTo) {
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
or
LocalFlow::localSsaFlowStep(_, nodeFrom, nodeTo)
or
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
or
LocalFlow::localFlowSsaInputFromRead(_, nodeFrom, nodeTo)
SsaFlow::localFlowStep(_, nodeFrom, nodeTo, _)
or
VariableCapture::flowInsensitiveStep(nodeFrom, nodeTo)
or
@@ -675,7 +561,8 @@ private module Cached {
/** Holds if `n` wraps an SSA definition without ingoing flow. */
private predicate entrySsaDefinition(SsaDefinitionExtNode n) {
n.getDefinitionExt() = any(SsaImpl::WriteDefinition def | not LocalFlow::ssaDefAssigns(def, _))
n.getDefinitionExt() =
any(SsaImpl::WriteDefinition def | not def.(Ssa::WriteDefinition).assigns(_))
}
pragma[nomagic]
@@ -715,13 +602,15 @@ private module Cached {
// Ensure all entry SSA definitions are local sources, except those that correspond
// to parameters (which are themselves local sources)
entrySsaDefinition(n) and
not LocalFlow::localFlowSsaParamInput(_, n)
not exists(SsaImpl::ParameterExt p |
p.isInitializedBy(n.(SsaDefinitionExtNode).getDefinitionExt())
)
or
isStoreTargetNode(n)
or
TypeTrackingInput::loadStep(_, n, _)
or
n instanceof BlockArgumentNode
n instanceof ImplicitBlockArgumentNode
}
cached
@@ -825,11 +714,7 @@ import Cached
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) {
n.(SsaDefinitionExtNode).isHidden()
or
n instanceof SsaInputNode
or
n = LocalFlow::getParameterDefNode(_)
n.(SsaNode).isHidden()
or
exists(AstNode desug |
isDesugarNode(desug) and
@@ -861,33 +746,55 @@ predicate nodeIsHidden(Node n) {
or
n instanceof CaptureNode
or
n instanceof BlockArgumentNode
n instanceof ImplicitBlockArgumentNode
}
/** An SSA definition, viewed as a node in a data flow graph. */
class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
/** An SSA node. */
abstract class SsaNode extends NodeImpl, TSsaNode {
SsaImpl::DataFlowIntegration::SsaNode node;
SsaImpl::DefinitionExt def;
SsaDefinitionExtNode() { this = TSsaDefinitionExtNode(def) }
SsaNode() {
this = TSsaNode(node) and
def = node.getDefinitionExt()
}
/** Gets the underlying SSA definition. */
SsaImpl::DefinitionExt getDefinitionExt() { result = def }
/** Holds if this node should be hidden from path explanations. */
abstract predicate isHidden();
override Location getLocationImpl() { result = node.getLocation() }
override string toStringImpl() { result = node.toString() }
}
/** An (extended) SSA definition, viewed as a node in a data flow graph. */
class SsaDefinitionExtNode extends SsaNode {
override SsaImpl::DataFlowIntegration::SsaDefinitionExtNode node;
/** Gets the underlying variable. */
Variable getVariable() { result = def.getSourceVariable() }
/** Holds if this node should be hidden from path explanations. */
predicate isHidden() {
override predicate isHidden() {
not def instanceof Ssa::WriteDefinition
or
isDesugarNode(def.(Ssa::WriteDefinition).getWriteAccess().getExpr())
or
def = getParameterDef(_)
}
override CfgScope getCfgScope() { result = def.getBasicBlock().getScope() }
}
override Location getLocationImpl() { result = def.getLocation() }
class SsaDefinitionNodeImpl extends SsaDefinitionExtNode {
Ssa::Definition ssaDef;
override string toStringImpl() { result = def.toString() }
SsaDefinitionNodeImpl() { ssaDef = def }
override Location getLocationImpl() { result = ssaDef.getLocation() }
override string toStringImpl() { result = ssaDef.toString() }
}
/**
@@ -925,20 +832,12 @@ class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
*
* both inputs into the phi read node after the outer condition are guarded.
*/
class SsaInputNode extends NodeImpl, TSsaInputNode {
SsaImpl::DefinitionExt def;
BasicBlock input;
class SsaInputNode extends SsaNode {
override SsaImpl::DataFlowIntegration::SsaInputNode node;
SsaInputNode() { this = TSsaInputNode(def, input) }
override predicate isHidden() { any() }
/** Gets the underlying SSA definition. */
SsaImpl::DefinitionExt getDefinitionExt() { result = def }
override CfgScope getCfgScope() { result = input.getScope() }
override Location getLocationImpl() { result = input.getLastNode().getLocation() }
override string toStringImpl() { result = "[input] " + def }
override CfgScope getCfgScope() { result = node.getDefinitionExt().getBasicBlock().getScope() }
}
/** An SSA definition for a `self` variable. */
@@ -1026,7 +925,7 @@ private module ParameterNodes {
* flow graph.
*/
class NormalParameterNode extends ParameterNodeImpl, TNormalParameterNode {
private Parameter parameter;
Parameter parameter;
NormalParameterNode() { this = TNormalParameterNode(parameter) }
@@ -1055,6 +954,9 @@ private module ParameterNodes {
// There are no positional parameters after the splat
not exists(SimpleParameter p, int m | m > n | p = callable.getParameter(m))
)
or
parameter = callable.getAParameter().(BlockParameter) and
pos.isBlock()
)
}
@@ -1162,24 +1064,32 @@ private module ParameterNodes {
* The value of a block parameter at function entry, viewed as a node in a data
* flow graph.
*/
class BlockParameterNode extends ParameterNodeImpl, TBlockParameterNode {
private MethodBase method;
BlockParameterNode() { this = TBlockParameterNode(method) }
final MethodBase getMethod() { result = method }
override Parameter getParameter() {
result = method.getAParameter() and result instanceof BlockParameter
}
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
c.asCfgScope() = method and pos.isBlock()
}
abstract class BlockParameterNode extends ParameterNodeImpl {
abstract MethodBase getMethod();
CfgNodes::ExprNodes::CallCfgNode getAYieldCall() {
this.getMethod() = result.getExpr().(YieldCall).getEnclosingMethod()
}
}
private class ExplicitBlockParameterNode extends BlockParameterNode, NormalParameterNode {
override BlockParameter parameter;
final override MethodBase getMethod() { result.getAParameter() = parameter }
}
private class ImplicitBlockParameterNode extends BlockParameterNode, TImplicitBlockParameterNode {
private MethodBase method;
ImplicitBlockParameterNode() { this = TImplicitBlockParameterNode(method) }
final override MethodBase getMethod() { result = method }
override Parameter getParameter() { none() }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
c.asCfgScope() = method and pos.isBlock()
}
override CfgScope getCfgScope() { result = method }
@@ -1452,10 +1362,10 @@ module ArgumentNodes {
}
}
class BlockArgumentNode extends NodeImpl, ArgumentNode, TBlockArgumentNode {
class ImplicitBlockArgumentNode extends NodeImpl, ArgumentNode, TImplicitBlockArgumentNode {
CfgNodes::ExprNodes::CallCfgNode yield;
BlockArgumentNode() { this = TBlockArgumentNode(yield) }
ImplicitBlockArgumentNode() { this = TImplicitBlockArgumentNode(yield) }
CfgNodes::ExprNodes::CallCfgNode getYieldCall() { result = yield }
@@ -1893,7 +1803,7 @@ predicate jumpStep(Node pred, Node succ) {
or
any(AdditionalJumpStep s).step(pred, succ)
or
succ.(BlockArgumentNode).getParameterNode(false) = pred
succ.(ImplicitBlockArgumentNode).getParameterNode(false) = pred
}
private ContentSet getArrayContent(int n) {
@@ -2236,7 +2146,7 @@ private predicate lambdaCallExpr(
*/
predicate lambdaSourceCall(CfgNodes::ExprNodes::CallCfgNode call, LambdaCallKind kind, Node receiver) {
kind = TYieldCallKind() and
call = receiver.(BlockArgumentNode).getYieldCall()
call = receiver.(ImplicitBlockArgumentNode).getYieldCall()
or
kind = TLambdaCallKind() and
lambdaCallExpr(call, receiver.asExpr())

View File

@@ -6,6 +6,7 @@ private import codeql.ruby.typetracking.internal.TypeTrackingImpl
private import codeql.ruby.dataflow.SSA
private import FlowSummaryImpl as FlowSummaryImpl
private import codeql.ruby.ApiGraphs
private import SsaImpl as SsaImpl
/**
* An element, viewed as a node in a data flow graph. Either an expression
@@ -360,16 +361,12 @@ class PostUpdateNode extends Node {
}
/** An SSA definition, viewed as a node in a data flow graph. */
class SsaDefinitionNode extends Node instanceof SsaDefinitionExtNode {
Ssa::Definition def;
SsaDefinitionNode() { this = TSsaDefinitionExtNode(def) }
class SsaDefinitionNode extends Node instanceof SsaDefinitionNodeImpl {
/** Gets the underlying SSA definition. */
Ssa::Definition getDefinition() { result = def }
Ssa::Definition getDefinition() { result = super.getDefinitionExt() }
/** Gets the underlying variable. */
Variable getVariable() { result = def.getSourceVariable() }
Variable getVariable() { result = this.getDefinition().getSourceVariable() }
}
cached
@@ -870,56 +867,7 @@ private predicate sameSourceVariable(Ssa::Definition def1, Ssa::Definition def2)
* in data flow and taint tracking.
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
private import SsaImpl as SsaImpl
pragma[nomagic]
private predicate guardChecksSsaDef(CfgNodes::AstCfgNode g, boolean branch, Ssa::Definition def) {
guardChecks(g, def.getARead(), branch)
}
pragma[nomagic]
private predicate guardControlsSsaRead(
CfgNodes::AstCfgNode g, boolean branch, Ssa::Definition def, Node n
) {
def.getARead() = n.asExpr() and
guardControlsBlock(g, n.asExpr().getBasicBlock(), branch)
}
pragma[nomagic]
private predicate guardControlsPhiInput(
CfgNodes::AstCfgNode g, boolean branch, Ssa::Definition def, BasicBlock input,
SsaInputDefinitionExt phi
) {
phi.hasInputFromBlock(def, _, _, input) and
(
guardControlsBlock(g, input, branch)
or
exists(SuccessorTypes::ConditionalSuccessor s |
g = input.getLastNode() and
s.getValue() = branch and
input.getASuccessor(s) = phi.getBasicBlock()
)
)
}
/** Gets a node that is safely guarded by the given guard check. */
Node getABarrierNode() {
exists(CfgNodes::AstCfgNode g, boolean branch, Ssa::Definition def |
guardChecksSsaDef(g, branch, def) and
guardControlsSsaRead(g, branch, def, result)
)
or
exists(
CfgNodes::AstCfgNode g, boolean branch, Ssa::Definition def, BasicBlock input,
SsaInputDefinitionExt phi
|
guardChecksSsaDef(g, branch, def) and
guardControlsPhiInput(g, branch, def, input, phi) and
result = TSsaInputNode(phi, input)
)
or
result.asExpr() = getAMaybeGuardedCapturedDef().getARead()
}
private import codeql.ruby.controlflow.internal.Guards
/**
* Gets an implicit entry definition for a captured variable that
@@ -928,6 +876,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
* This is restricted to calls where the variable is captured inside a
* block.
*/
pragma[nomagic]
private Ssa::CapturedEntryDefinition getAMaybeGuardedCapturedDef() {
exists(
CfgNodes::ExprCfgNode g, boolean branch, CfgNodes::ExprCfgNode testedNode,
@@ -940,15 +889,14 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
sameSourceVariable(def, result)
)
}
}
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
private predicate guardControlsBlock(CfgNodes::AstCfgNode guard, BasicBlock bb, boolean branch) {
exists(ConditionBlock conditionBlock, SuccessorTypes::ConditionalSuccessor s |
guard = conditionBlock.getLastNode() and
s.getValue() = branch and
conditionBlock.controls(bb, s)
)
/** Gets a node that is safely guarded by the given guard check. */
Node getABarrierNode() {
SsaFlow::asNode(result) =
SsaImpl::DataFlowIntegration::BarrierGuard<guardChecks/3>::getABarrierNode()
or
result.asExpr() = getAMaybeGuardedCapturedDef().getARead()
}
}
/**

View File

@@ -6,7 +6,7 @@ private import codeql.ruby.dataflow.SSA
private import codeql.ruby.ast.Variable
private import Cfg::CfgNodes::ExprNodes
private module SsaInput implements SsaImplCommon::InputSig<Location> {
module SsaInput implements SsaImplCommon::InputSig<Location> {
private import codeql.ruby.controlflow.ControlFlowGraph as Cfg
private import codeql.ruby.controlflow.BasicBlocks as BasicBlocks
@@ -65,7 +65,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
}
}
private import SsaImplCommon::Make<Location, SsaInput> as Impl
import SsaImplCommon::Make<Location, SsaInput> as Impl
class Definition = Impl::Definition;
@@ -283,15 +283,6 @@ private predicate adjacentDefSkipUncertainReads(
SsaInput::variableRead(bb2, i2, _, true)
}
/** Same as `adjacentDefReadExt`, but skips uncertain reads. */
pragma[nomagic]
private predicate adjacentDefSkipUncertainReadsExt(
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
) {
adjacentDefReachesReadExt(def, bb1, i1, bb2, i2) and
SsaInput::variableRead(bb2, i2, _, true)
}
private predicate adjacentDefReachesUncertainReadExt(
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
) {
@@ -393,19 +384,6 @@ private module Cached {
)
}
/**
* Holds if the value defined at SSA definition `def` can reach a read at `read`,
* without passing through any other non-pseudo read.
*/
cached
predicate firstReadExt(DefinitionExt def, VariableReadAccessCfgNode read) {
exists(Cfg::BasicBlock bb1, int i1, Cfg::BasicBlock bb2, int i2 |
def.definesAt(_, bb1, i1, _) and
adjacentDefSkipUncertainReadsExt(def, bb1, i1, bb2, i2) and
read = bb2.getNode(i2)
)
}
/**
* Holds if the read at `read2` is a read of the same SSA definition `def`
* as the read at `read1`, and `read2` can be reached from `read1` without
@@ -423,23 +401,6 @@ private module Cached {
)
}
/**
* Holds if the read at `read2` is a read of the same SSA definition `def`
* as the read at `read1`, and `read2` can be reached from `read1` without
* passing through another non-pseudo read.
*/
cached
predicate adjacentReadPairExt(
DefinitionExt def, VariableReadAccessCfgNode read1, VariableReadAccessCfgNode read2
) {
exists(Cfg::BasicBlock bb1, int i1, Cfg::BasicBlock bb2, int i2 |
read1 = bb1.getNode(i1) and
variableReadActual(bb1, i1, _) and
adjacentDefSkipUncertainReadsExt(def, bb1, i1, bb2, i2) and
read2 = bb2.getNode(i2)
)
}
/**
* Holds if the read of `def` at `read` may be a last read. That is, `read`
* can either reach another definition of the underlying source variable or
@@ -454,32 +415,42 @@ private module Cached {
)
}
/**
* Holds if the reference to `def` at index `i` in basic block `bb` can reach
* another definition `next` of the same underlying source variable, without
* passing through another write or non-pseudo read.
*
* The reference is either a read of `def` or `def` itself.
*/
cached
predicate lastRefBeforeRedefExt(
DefinitionExt def, Cfg::BasicBlock bb, int i, Cfg::BasicBlock input, DefinitionExt next
) {
exists(LocalVariable v |
Impl::lastRefRedefExt(def, v, bb, i, input, next) and
not SsaInput::variableRead(bb, i, v, false)
)
or
exists(SsaInput::BasicBlock bb0, int i0 |
Impl::lastRefRedefExt(def, _, bb0, i0, input, next) and
adjacentDefReachesUncertainReadExt(def, bb, i, bb0, i0)
)
}
cached
Definition uncertainWriteDefinitionInput(UncertainWriteDefinition def) {
Impl::uncertainWriteDefinitionInput(def, result)
}
cached
module DataFlowIntegration {
import DataFlowIntegrationImpl
cached
predicate localFlowStep(DefinitionExt def, Node nodeFrom, Node nodeTo, boolean isUseStep) {
DataFlowIntegrationImpl::localFlowStep(def, nodeFrom, nodeTo, isUseStep)
}
cached
predicate localMustFlowStep(DefinitionExt def, Node nodeFrom, Node nodeTo) {
DataFlowIntegrationImpl::localMustFlowStep(def, nodeFrom, nodeTo)
}
signature predicate guardChecksSig(Cfg::CfgNodes::AstCfgNode g, Cfg::CfgNode e, boolean branch);
cached // nothing is actually cached
module BarrierGuard<guardChecksSig/3 guardChecks> {
private predicate guardChecksAdjTypes(
DataFlowIntegrationInput::Guard g, DataFlowIntegrationInput::Expr e, boolean branch
) {
guardChecks(g, e, branch)
}
private Node getABarrierNodeImpl() {
result = DataFlowIntegrationImpl::BarrierGuard<guardChecksAdjTypes/3>::getABarrierNode()
}
predicate getABarrierNode = getABarrierNodeImpl/0;
}
}
}
import Cached
@@ -510,3 +481,97 @@ class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
override Location getLocation() { result = Impl::PhiReadNode.super.getLocation() }
}
class NormalParameter extends Parameter {
NormalParameter() {
this instanceof SimpleParameter or
this instanceof OptionalParameter or
this instanceof KeywordParameter or
this instanceof HashSplatParameter or
this instanceof SplatParameter or
this instanceof BlockParameter
}
}
/** Gets the SSA definition node corresponding to parameter `p`. */
pragma[nomagic]
DefinitionExt getParameterDef(NamedParameter p) {
exists(Cfg::BasicBlock bb, int i |
bb.getNode(i).getAstNode() = p.getDefiningAccess() and
result.definesAt(_, bb, i, _)
)
}
private newtype TParameterExt =
TNormalParameter(NormalParameter p) or
TSelfMethodParameter(MethodBase m) or
TSelfToplevelParameter(Toplevel t)
/** A normal parameter or an implicit `self` parameter. */
class ParameterExt extends TParameterExt {
NormalParameter asParameter() { this = TNormalParameter(result) }
MethodBase asMethodSelf() { this = TSelfMethodParameter(result) }
Toplevel asToplevelSelf() { this = TSelfToplevelParameter(result) }
predicate isInitializedBy(WriteDefinition def) {
def = getParameterDef(this.asParameter())
or
def.(Ssa::SelfDefinition).getSourceVariable().getDeclaringScope() =
[this.asMethodSelf().(Scope), this.asToplevelSelf()]
}
string toString() {
result =
[
this.asParameter().toString(), this.asMethodSelf().toString(),
this.asToplevelSelf().toString()
]
}
Location getLocation() {
result =
[
this.asParameter().getLocation(), this.asMethodSelf().getLocation(),
this.asToplevelSelf().getLocation()
]
}
}
private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInputSig {
private import codeql.ruby.controlflow.internal.Guards as Guards
class Parameter = ParameterExt;
class Expr extends Cfg::CfgNodes::ExprCfgNode {
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { this = bb.getNode(i) }
}
Expr getARead(Definition def) { result = Cached::getARead(def) }
predicate ssaDefAssigns(WriteDefinition def, Expr value) {
def.(Ssa::WriteDefinition).assigns(value)
}
predicate ssaDefInitializesParam(WriteDefinition def, Parameter p) { p.isInitializedBy(def) }
class Guard extends Cfg::CfgNodes::AstCfgNode {
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { this = bb.getNode(i) }
}
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
predicate guardControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {
Guards::guardControlsBlock(guard, bb, branch)
}
/** Gets an immediate conditional successor of basic block `bb`, if any. */
SsaInput::BasicBlock getAConditionalBasicBlockSuccessor(SsaInput::BasicBlock bb, boolean branch) {
exists(Cfg::SuccessorTypes::ConditionalSuccessor s |
result = bb.getASuccessor(s) and
s.getValue() = branch
)
}
}
private module DataFlowIntegrationImpl = Impl::DataFlowIntegration<DataFlowIntegrationInput>;

View File

@@ -5,6 +5,7 @@ private import codeql.ruby.CFG
private import codeql.ruby.DataFlow
private import FlowSummaryImpl as FlowSummaryImpl
private import codeql.ruby.dataflow.SSA
private import SsaImpl as SsaImpl
/**
* Holds if `node` should be a sanitizer in all global taint flow configurations
@@ -89,7 +90,7 @@ private module Cached {
clause = case.getBranch(_) and
def = nodeTo.(SsaDefinitionExtNode).getDefinitionExt() and
def.getControlFlowNode() = variablesInPattern(clause.getPattern()) and
not LocalFlow::ssaDefAssigns(def, value)
not def.(Ssa::WriteDefinition).assigns(value)
)
or
// operation involving `nodeFrom`

View File

@@ -29,7 +29,7 @@ class NetHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode {
this = request
|
// Net::HTTP.get(...)
method = "get" and
method in ["get", "get_response"] and
requestNode = API::getTopLevelMember("Net").getMember("HTTP").getReturn(method) and
returnsResponseBody = true
or

View File

@@ -10,14 +10,14 @@ edges
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:26:31:26:37 | tainted | provenance | |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:30:24:30:30 | tainted | provenance | |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:31:27:31:33 | tainted | provenance | |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:51:24:51:30 | tainted | provenance | |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:56:22:56:28 | tainted | provenance | |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:57:17:57:23 | tainted | provenance | |
@@ -27,30 +27,30 @@ edges
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:122:16:122:22 | tainted | provenance | |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:128:14:128:20 | tainted | provenance | |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | Sink:MaD:3 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | Sink:MaD:3 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted | provenance | Sink:MaD:3 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted | provenance | Sink:MaD:3 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted | provenance | Sink:MaD:4 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted | provenance | Sink:MaD:4 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted | provenance | Sink:MaD:1 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted | provenance | Sink:MaD:1 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted | provenance | Sink:MaD:0 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted | provenance | Sink:MaD:0 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted | provenance | Sink:MaD:2 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted | provenance | Sink:MaD:2 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted | provenance | Sink:MaD:5 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted | provenance | Sink:MaD:5 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted | provenance | Sink:MaD:5 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted | provenance | Sink:MaD:5 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted | provenance | Sink:MaD:5 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted | provenance | Sink:MaD:5 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | Sink:MaD:65 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | Sink:MaD:65 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted | provenance | Sink:MaD:65 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted | provenance | Sink:MaD:65 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted | provenance | Sink:MaD:66 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted | provenance | Sink:MaD:66 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted | provenance | Sink:MaD:63 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted | provenance | Sink:MaD:63 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted | provenance | Sink:MaD:62 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted | provenance | Sink:MaD:62 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted | provenance | Sink:MaD:64 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted | provenance | Sink:MaD:64 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted | provenance | Sink:MaD:67 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted | provenance | Sink:MaD:67 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted | provenance | Sink:MaD:67 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted | provenance | Sink:MaD:67 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted | provenance | Sink:MaD:67 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted | provenance | Sink:MaD:67 |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:157:14:160:3 | do ... end [captured tainted] | provenance | |
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:157:14:160:3 | do ... end [captured tainted] | provenance | |
| summaries.rb:1:20:1:36 | call to source | summaries.rb:1:11:1:36 | call to identity | provenance | |
@@ -81,34 +81,34 @@ edges
| summaries.rb:16:36:16:42 | tainted | summaries.rb:16:12:16:43 | call to apply_lambda | provenance | |
| summaries.rb:20:1:20:8 | tainted4 | summaries.rb:21:6:21:13 | tainted4 | provenance | |
| summaries.rb:20:12:20:32 | call to firstArg | summaries.rb:20:1:20:8 | tainted4 | provenance | |
| summaries.rb:20:25:20:31 | tainted | summaries.rb:20:12:20:32 | call to firstArg | provenance | MaD:11 |
| summaries.rb:20:25:20:31 | tainted | summaries.rb:20:12:20:32 | call to firstArg | provenance | MaD:73 |
| summaries.rb:26:1:26:8 | tainted5 | summaries.rb:27:6:27:13 | tainted5 | provenance | |
| summaries.rb:26:12:26:38 | call to secondArg | summaries.rb:26:1:26:8 | tainted5 | provenance | |
| summaries.rb:26:31:26:37 | tainted | summaries.rb:26:12:26:38 | call to secondArg | provenance | MaD:17 |
| summaries.rb:30:24:30:30 | tainted | summaries.rb:30:6:30:42 | call to onlyWithBlock | provenance | MaD:15 |
| summaries.rb:31:27:31:33 | tainted | summaries.rb:31:6:31:34 | call to onlyWithoutBlock | provenance | MaD:16 |
| summaries.rb:26:31:26:37 | tainted | summaries.rb:26:12:26:38 | call to secondArg | provenance | MaD:79 |
| summaries.rb:30:24:30:30 | tainted | summaries.rb:30:6:30:42 | call to onlyWithBlock | provenance | MaD:77 |
| summaries.rb:31:27:31:33 | tainted | summaries.rb:31:6:31:34 | call to onlyWithoutBlock | provenance | MaD:78 |
| summaries.rb:40:3:40:3 | t | summaries.rb:41:24:41:24 | t | provenance | |
| summaries.rb:40:3:40:3 | t | summaries.rb:42:24:42:24 | t | provenance | |
| summaries.rb:40:3:40:3 | t | summaries.rb:44:8:44:8 | t | provenance | |
| summaries.rb:40:7:40:17 | call to source | summaries.rb:40:3:40:3 | t | provenance | |
| summaries.rb:41:24:41:24 | t | summaries.rb:41:8:41:25 | call to matchedByName | provenance | MaD:24 |
| summaries.rb:42:24:42:24 | t | summaries.rb:42:8:42:25 | call to matchedByName | provenance | MaD:24 |
| summaries.rb:44:8:44:8 | t | summaries.rb:44:8:44:27 | call to matchedByNameRcv | provenance | MaD:23 |
| summaries.rb:48:24:48:41 | call to source | summaries.rb:48:8:48:42 | call to preserveTaint | provenance | MaD:10 |
| summaries.rb:51:24:51:30 | tainted | summaries.rb:51:6:51:31 | call to namedArg | provenance | MaD:14 |
| summaries.rb:41:24:41:24 | t | summaries.rb:41:8:41:25 | call to matchedByName | provenance | MaD:86 |
| summaries.rb:42:24:42:24 | t | summaries.rb:42:8:42:25 | call to matchedByName | provenance | MaD:86 |
| summaries.rb:44:8:44:8 | t | summaries.rb:44:8:44:27 | call to matchedByNameRcv | provenance | MaD:85 |
| summaries.rb:48:24:48:41 | call to source | summaries.rb:48:8:48:42 | call to preserveTaint | provenance | MaD:72 |
| summaries.rb:51:24:51:30 | tainted | summaries.rb:51:6:51:31 | call to namedArg | provenance | MaD:76 |
| summaries.rb:53:1:53:4 | args [element :foo] | summaries.rb:54:21:54:24 | args [element :foo] | provenance | |
| summaries.rb:53:8:53:33 | call to [] [element :foo] | summaries.rb:53:1:53:4 | args [element :foo] | provenance | |
| summaries.rb:53:15:53:31 | call to source | summaries.rb:53:8:53:33 | call to [] [element :foo] | provenance | |
| summaries.rb:54:19:54:24 | ** ... [element :foo] | summaries.rb:54:6:54:25 | call to namedArg | provenance | MaD:14 |
| summaries.rb:54:19:54:24 | ** ... [element :foo] | summaries.rb:54:6:54:25 | call to namedArg | provenance | MaD:76 |
| summaries.rb:54:21:54:24 | args [element :foo] | summaries.rb:54:19:54:24 | ** ... [element :foo] | provenance | |
| summaries.rb:56:22:56:28 | tainted | summaries.rb:56:6:56:29 | call to anyArg | provenance | MaD:7 |
| summaries.rb:57:17:57:23 | tainted | summaries.rb:57:6:57:24 | call to anyArg | provenance | MaD:7 |
| summaries.rb:59:27:59:33 | tainted | summaries.rb:59:6:59:34 | call to anyNamedArg | provenance | MaD:8 |
| summaries.rb:63:32:63:38 | tainted | summaries.rb:63:6:63:39 | call to anyPositionFromOne | provenance | MaD:9 |
| summaries.rb:65:23:65:29 | tainted | summaries.rb:65:40:65:40 | x | provenance | MaD:12 |
| summaries.rb:56:22:56:28 | tainted | summaries.rb:56:6:56:29 | call to anyArg | provenance | MaD:69 |
| summaries.rb:57:17:57:23 | tainted | summaries.rb:57:6:57:24 | call to anyArg | provenance | MaD:69 |
| summaries.rb:59:27:59:33 | tainted | summaries.rb:59:6:59:34 | call to anyNamedArg | provenance | MaD:70 |
| summaries.rb:63:32:63:38 | tainted | summaries.rb:63:6:63:39 | call to anyPositionFromOne | provenance | MaD:71 |
| summaries.rb:65:23:65:29 | tainted | summaries.rb:65:40:65:40 | x | provenance | MaD:74 |
| summaries.rb:65:40:65:40 | x | summaries.rb:66:8:66:8 | x | provenance | |
| summaries.rb:73:24:73:53 | call to source | summaries.rb:73:8:73:54 | call to preserveTaint | provenance | MaD:18 |
| summaries.rb:76:26:76:56 | call to source | summaries.rb:76:8:76:57 | call to preserveTaint | provenance | MaD:19 |
| summaries.rb:73:24:73:53 | call to source | summaries.rb:73:8:73:54 | call to preserveTaint | provenance | MaD:80 |
| summaries.rb:76:26:76:56 | call to source | summaries.rb:76:8:76:57 | call to preserveTaint | provenance | MaD:81 |
| summaries.rb:79:1:79:1 | a [element 1] | summaries.rb:82:6:82:6 | a [element 1] | provenance | |
| summaries.rb:79:1:79:1 | a [element 1] | summaries.rb:82:6:82:6 | a [element 1] | provenance | |
| summaries.rb:79:1:79:1 | a [element 1] | summaries.rb:83:6:83:6 | a [element 1] | provenance | |
@@ -145,12 +145,12 @@ edges
| summaries.rb:81:1:81:1 | [post] a [element] | summaries.rb:95:1:95:1 | a [element] | provenance | |
| summaries.rb:81:13:81:27 | call to source | summaries.rb:81:1:81:1 | [post] a [element] | provenance | |
| summaries.rb:81:13:81:27 | call to source | summaries.rb:81:1:81:1 | [post] a [element] | provenance | |
| summaries.rb:82:6:82:6 | a [element 1] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:25 |
| summaries.rb:82:6:82:6 | a [element 1] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:25 |
| summaries.rb:82:6:82:6 | a [element] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:25 |
| summaries.rb:82:6:82:6 | a [element] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:25 |
| summaries.rb:83:6:83:6 | a [element 1] | summaries.rb:83:6:83:31 | call to readExactlyElementOne | provenance | MaD:26 |
| summaries.rb:83:6:83:6 | a [element 1] | summaries.rb:83:6:83:31 | call to readExactlyElementOne | provenance | MaD:26 |
| summaries.rb:82:6:82:6 | a [element 1] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:87 |
| summaries.rb:82:6:82:6 | a [element 1] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:87 |
| summaries.rb:82:6:82:6 | a [element] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:87 |
| summaries.rb:82:6:82:6 | a [element] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:87 |
| summaries.rb:83:6:83:6 | a [element 1] | summaries.rb:83:6:83:31 | call to readExactlyElementOne | provenance | MaD:88 |
| summaries.rb:83:6:83:6 | a [element 1] | summaries.rb:83:6:83:31 | call to readExactlyElementOne | provenance | MaD:88 |
| summaries.rb:84:6:84:6 | a [element] | summaries.rb:84:6:84:9 | ...[...] | provenance | |
| summaries.rb:84:6:84:6 | a [element] | summaries.rb:84:6:84:9 | ...[...] | provenance | |
| summaries.rb:85:6:85:6 | a [element 1] | summaries.rb:85:6:85:9 | ...[...] | provenance | |
@@ -169,10 +169,10 @@ edges
| summaries.rb:87:1:87:1 | b [element] | summaries.rb:89:6:89:6 | b [element] | provenance | |
| summaries.rb:87:1:87:1 | b [element] | summaries.rb:90:6:90:6 | b [element] | provenance | |
| summaries.rb:87:1:87:1 | b [element] | summaries.rb:90:6:90:6 | b [element] | provenance | |
| summaries.rb:87:5:87:5 | a [element 1] | summaries.rb:87:5:87:22 | call to withElementOne [element 1] | provenance | MaD:28 |
| summaries.rb:87:5:87:5 | a [element 1] | summaries.rb:87:5:87:22 | call to withElementOne [element 1] | provenance | MaD:28 |
| summaries.rb:87:5:87:5 | a [element] | summaries.rb:87:5:87:22 | call to withElementOne [element] | provenance | MaD:28 |
| summaries.rb:87:5:87:5 | a [element] | summaries.rb:87:5:87:22 | call to withElementOne [element] | provenance | MaD:28 |
| summaries.rb:87:5:87:5 | a [element 1] | summaries.rb:87:5:87:22 | call to withElementOne [element 1] | provenance | MaD:90 |
| summaries.rb:87:5:87:5 | a [element 1] | summaries.rb:87:5:87:22 | call to withElementOne [element 1] | provenance | MaD:90 |
| summaries.rb:87:5:87:5 | a [element] | summaries.rb:87:5:87:22 | call to withElementOne [element] | provenance | MaD:90 |
| summaries.rb:87:5:87:5 | a [element] | summaries.rb:87:5:87:22 | call to withElementOne [element] | provenance | MaD:90 |
| summaries.rb:87:5:87:22 | call to withElementOne [element 1] | summaries.rb:87:1:87:1 | b [element 1] | provenance | |
| summaries.rb:87:5:87:22 | call to withElementOne [element 1] | summaries.rb:87:1:87:1 | b [element 1] | provenance | |
| summaries.rb:87:5:87:22 | call to withElementOne [element] | summaries.rb:87:1:87:1 | b [element] | provenance | |
@@ -187,8 +187,8 @@ edges
| summaries.rb:90:6:90:6 | b [element] | summaries.rb:90:6:90:9 | ...[...] | provenance | |
| summaries.rb:91:1:91:1 | c [element 1] | summaries.rb:93:6:93:6 | c [element 1] | provenance | |
| summaries.rb:91:1:91:1 | c [element 1] | summaries.rb:93:6:93:6 | c [element 1] | provenance | |
| summaries.rb:91:5:91:5 | a [element 1] | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | provenance | MaD:29 |
| summaries.rb:91:5:91:5 | a [element 1] | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | provenance | MaD:29 |
| summaries.rb:91:5:91:5 | a [element 1] | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | provenance | MaD:91 |
| summaries.rb:91:5:91:5 | a [element 1] | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | provenance | MaD:91 |
| summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | summaries.rb:91:1:91:1 | c [element 1] | provenance | |
| summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | summaries.rb:91:1:91:1 | c [element 1] | provenance | |
| summaries.rb:93:6:93:6 | c [element 1] | summaries.rb:93:6:93:9 | ...[...] | provenance | |
@@ -203,10 +203,10 @@ edges
| summaries.rb:95:1:95:1 | [post] a [element] | summaries.rb:97:6:97:6 | a [element] | provenance | |
| summaries.rb:95:1:95:1 | [post] a [element] | summaries.rb:98:6:98:6 | a [element] | provenance | |
| summaries.rb:95:1:95:1 | [post] a [element] | summaries.rb:98:6:98:6 | a [element] | provenance | |
| summaries.rb:95:1:95:1 | a [element 2] | summaries.rb:95:1:95:1 | [post] a [element 2] | provenance | MaD:32 |
| summaries.rb:95:1:95:1 | a [element 2] | summaries.rb:95:1:95:1 | [post] a [element 2] | provenance | MaD:32 |
| summaries.rb:95:1:95:1 | a [element] | summaries.rb:95:1:95:1 | [post] a [element] | provenance | MaD:32 |
| summaries.rb:95:1:95:1 | a [element] | summaries.rb:95:1:95:1 | [post] a [element] | provenance | MaD:32 |
| summaries.rb:95:1:95:1 | a [element 2] | summaries.rb:95:1:95:1 | [post] a [element 2] | provenance | MaD:94 |
| summaries.rb:95:1:95:1 | a [element 2] | summaries.rb:95:1:95:1 | [post] a [element 2] | provenance | MaD:94 |
| summaries.rb:95:1:95:1 | a [element] | summaries.rb:95:1:95:1 | [post] a [element] | provenance | MaD:94 |
| summaries.rb:95:1:95:1 | a [element] | summaries.rb:95:1:95:1 | [post] a [element] | provenance | MaD:94 |
| summaries.rb:96:6:96:6 | a [element] | summaries.rb:96:6:96:9 | ...[...] | provenance | |
| summaries.rb:96:6:96:6 | a [element] | summaries.rb:96:6:96:9 | ...[...] | provenance | |
| summaries.rb:97:6:97:6 | a [element] | summaries.rb:97:6:97:9 | ...[...] | provenance | |
@@ -217,8 +217,8 @@ edges
| summaries.rb:98:6:98:6 | a [element] | summaries.rb:98:6:98:9 | ...[...] | provenance | |
| summaries.rb:99:1:99:1 | [post] a [element 2] | summaries.rb:102:6:102:6 | a [element 2] | provenance | |
| summaries.rb:99:1:99:1 | [post] a [element 2] | summaries.rb:102:6:102:6 | a [element 2] | provenance | |
| summaries.rb:99:1:99:1 | a [element 2] | summaries.rb:99:1:99:1 | [post] a [element 2] | provenance | MaD:31 |
| summaries.rb:99:1:99:1 | a [element 2] | summaries.rb:99:1:99:1 | [post] a [element 2] | provenance | MaD:31 |
| summaries.rb:99:1:99:1 | a [element 2] | summaries.rb:99:1:99:1 | [post] a [element 2] | provenance | MaD:93 |
| summaries.rb:99:1:99:1 | a [element 2] | summaries.rb:99:1:99:1 | [post] a [element 2] | provenance | MaD:93 |
| summaries.rb:102:6:102:6 | a [element 2] | summaries.rb:102:6:102:9 | ...[...] | provenance | |
| summaries.rb:102:6:102:6 | a [element 2] | summaries.rb:102:6:102:9 | ...[...] | provenance | |
| summaries.rb:103:1:103:1 | [post] d [element 3] | summaries.rb:104:1:104:1 | d [element 3] | provenance | |
@@ -227,39 +227,39 @@ edges
| summaries.rb:103:8:103:22 | call to source | summaries.rb:103:1:103:1 | [post] d [element 3] | provenance | |
| summaries.rb:104:1:104:1 | [post] d [element 3] | summaries.rb:108:6:108:6 | d [element 3] | provenance | |
| summaries.rb:104:1:104:1 | [post] d [element 3] | summaries.rb:108:6:108:6 | d [element 3] | provenance | |
| summaries.rb:104:1:104:1 | d [element 3] | summaries.rb:104:1:104:1 | [post] d [element 3] | provenance | MaD:30 |
| summaries.rb:104:1:104:1 | d [element 3] | summaries.rb:104:1:104:1 | [post] d [element 3] | provenance | MaD:30 |
| summaries.rb:104:1:104:1 | d [element 3] | summaries.rb:104:1:104:1 | [post] d [element 3] | provenance | MaD:92 |
| summaries.rb:104:1:104:1 | d [element 3] | summaries.rb:104:1:104:1 | [post] d [element 3] | provenance | MaD:92 |
| summaries.rb:108:6:108:6 | d [element 3] | summaries.rb:108:6:108:9 | ...[...] | provenance | |
| summaries.rb:108:6:108:6 | d [element 3] | summaries.rb:108:6:108:9 | ...[...] | provenance | |
| summaries.rb:111:1:111:1 | [post] x [@value] | summaries.rb:112:6:112:6 | x [@value] | provenance | |
| summaries.rb:111:1:111:1 | [post] x [@value] | summaries.rb:112:6:112:6 | x [@value] | provenance | |
| summaries.rb:111:13:111:26 | call to source | summaries.rb:111:1:111:1 | [post] x [@value] | provenance | MaD:27 |
| summaries.rb:111:13:111:26 | call to source | summaries.rb:111:1:111:1 | [post] x [@value] | provenance | MaD:27 |
| summaries.rb:112:6:112:6 | x [@value] | summaries.rb:112:6:112:16 | call to get_value | provenance | MaD:22 |
| summaries.rb:112:6:112:6 | x [@value] | summaries.rb:112:6:112:16 | call to get_value | provenance | MaD:22 |
| summaries.rb:111:13:111:26 | call to source | summaries.rb:111:1:111:1 | [post] x [@value] | provenance | MaD:89 |
| summaries.rb:111:13:111:26 | call to source | summaries.rb:111:1:111:1 | [post] x [@value] | provenance | MaD:89 |
| summaries.rb:112:6:112:6 | x [@value] | summaries.rb:112:6:112:16 | call to get_value | provenance | MaD:84 |
| summaries.rb:112:6:112:6 | x [@value] | summaries.rb:112:6:112:16 | call to get_value | provenance | MaD:84 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:128:14:128:20 | tainted | provenance | |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:131:16:131:22 | tainted | provenance | |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:131:16:131:22 | tainted | provenance | Sink:MaD:3 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:132:21:132:27 | tainted | provenance | Sink:MaD:3 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:135:26:135:32 | tainted | provenance | Sink:MaD:4 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:137:23:137:29 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:140:19:140:25 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:141:19:141:25 | tainted | provenance | Sink:MaD:6 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:145:26:145:32 | tainted | provenance | Sink:MaD:1 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:147:16:147:22 | tainted | provenance | Sink:MaD:0 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:150:39:150:45 | tainted | provenance | Sink:MaD:2 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:154:20:154:26 | tainted | provenance | Sink:MaD:5 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:155:28:155:34 | tainted | provenance | Sink:MaD:5 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:156:27:156:33 | tainted | provenance | Sink:MaD:5 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:131:16:131:22 | tainted | provenance | Sink:MaD:65 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:132:21:132:27 | tainted | provenance | Sink:MaD:65 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:135:26:135:32 | tainted | provenance | Sink:MaD:66 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:137:23:137:29 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:140:19:140:25 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:141:19:141:25 | tainted | provenance | Sink:MaD:68 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:145:26:145:32 | tainted | provenance | Sink:MaD:63 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:147:16:147:22 | tainted | provenance | Sink:MaD:62 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:150:39:150:45 | tainted | provenance | Sink:MaD:64 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:154:20:154:26 | tainted | provenance | Sink:MaD:67 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:155:28:155:34 | tainted | provenance | Sink:MaD:67 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:156:27:156:33 | tainted | provenance | Sink:MaD:67 |
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:157:14:160:3 | do ... end [captured tainted] | provenance | |
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:16:122:22 | [post] tainted | provenance | MaD:20 |
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:25:122:25 | [post] y | provenance | MaD:20 |
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:33:122:33 | [post] z | provenance | MaD:20 |
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:16:122:22 | [post] tainted | provenance | MaD:82 |
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:25:122:25 | [post] y | provenance | MaD:82 |
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:33:122:33 | [post] z | provenance | MaD:82 |
| summaries.rb:122:25:122:25 | [post] y | summaries.rb:124:6:124:6 | y | provenance | |
| summaries.rb:122:33:122:33 | [post] z | summaries.rb:125:6:125:6 | z | provenance | |
| summaries.rb:128:1:128:1 | [post] x | summaries.rb:129:6:129:6 | x | provenance | |
| summaries.rb:128:14:128:20 | tainted | summaries.rb:128:1:128:1 | [post] x | provenance | MaD:21 |
| summaries.rb:131:16:131:22 | tainted | summaries.rb:131:1:131:23 | synthetic splat argument | provenance | Sink:MaD:3 |
| summaries.rb:128:14:128:20 | tainted | summaries.rb:128:1:128:1 | [post] x | provenance | MaD:83 |
| summaries.rb:131:16:131:22 | tainted | summaries.rb:131:1:131:23 | synthetic splat argument | provenance | Sink:MaD:65 |
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | summaries.rb:158:15:158:21 | tainted | provenance | heuristic-callback |
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | summaries.rb:158:15:158:21 | tainted | provenance | heuristic-callback |
nodes