Merge branch 'main' into json-log

This commit is contained in:
Arthur Baars
2023-01-30 10:49:42 +01:00
committed by GitHub
1341 changed files with 263640 additions and 24876 deletions

BIN
ruby/Cargo.lock generated

Binary file not shown.

View File

@@ -3,12 +3,14 @@ description: Builds the Ruby CodeQL pack
runs:
using: composite
steps:
- uses: ./.github/actions/os-version
id: os_version
- name: Cache entire extractor
id: cache-extractor
uses: actions/cache@v3
with:
path: ruby/extractor-pack
key: ${{ runner.os }}-extractor-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}-${{ hashFiles('ruby/**/*.rs') }}-${{ hashFiles('ruby/codeql-extractor.yml', 'ruby/downgrades', 'ruby/tools', 'ruby/ql/lib/ruby.dbscheme', 'ruby/ql/lib/ruby.dbscheme.stats') }}
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-extractor-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/scripts/create-extractor-pack.sh', 'ruby/**/Cargo.lock', 'ruby/actions/create-extractor-pack/action.yml') }}-${{ hashFiles('ruby/**/*.rs') }}-${{ hashFiles('ruby/codeql-extractor.yml', 'ruby/downgrades', 'ruby/tools', 'ruby/ql/lib/ruby.dbscheme', 'ruby/ql/lib/ruby.dbscheme.stats') }}
- name: Cache cargo
uses: actions/cache@v3
if: steps.cache-extractor.outputs.cache-hit != 'true'
@@ -17,9 +19,11 @@ runs:
~/.cargo/registry
~/.cargo/git
ruby/target
key: ${{ runner.os }}-ruby-qltest-cargo-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-qltest-cargo-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/scripts/create-extractor-pack.sh', 'ruby/**/Cargo.lock') }}
- name: Build Extractor
if: steps.cache-extractor.outputs.cache-hit != 'true'
shell: bash
run: scripts/create-extractor-pack.sh
run: |
cargo install cross --version 0.2.1
scripts/create-extractor-pack.sh
working-directory: ruby

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
description: Update grammar
compatibility: backwards
ruby_splat_argument_def.rel: reorder ruby_splat_argument_child.rel ( int id, int child) id child
ruby_splat_argument_child.rel: delete
ruby_hash_splat_argument_def.rel: reorder ruby_hash_splat_argument_child.rel ( int id, int child) id child
ruby_hash_splat_argument_child.rel: delete

View File

@@ -9,15 +9,15 @@ edition = "2018"
[dependencies]
flate2 = "1.0"
node-types = { path = "../node-types" }
tree-sitter = "0.19"
tree-sitter-embedded-template = { git = "https://github.com/tree-sitter/tree-sitter-embedded-template.git", rev = "1a538da253d73f896b9f6c0c7d79cda58791ac5c" }
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "ad1043283b1f9daf4aad381b6a81f18a5a27fe7e" }
tree-sitter = "0.20"
tree-sitter-embedded-template = { git = "https://github.com/tree-sitter/tree-sitter-embedded-template.git", rev = "a13085849cf69e2401ec44e38cffc3d73f22f3df" }
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "7a1921bcfd90e3a04c1ad011059087aaf0168dd4" }
clap = "3.0"
tracing = "0.1"
tracing-subscriber = { version = "0.3.3", features = ["env-filter"] }
rayon = "1.5.0"
num_cpus = "1.13.0"
regex = "1.5.5"
num_cpus = "1.14.0"
regex = "1.7.1"
encoding = "0.2"
lazy_static = "1.4.0"
serde = { version = "1.0", features = ["derive"] }

View File

@@ -11,5 +11,5 @@ clap = "3.0"
node-types = { path = "../node-types" }
tracing = "0.1"
tracing-subscriber = { version = "0.3.3", features = ["env-filter"] }
tree-sitter-embedded-template = { git = "https://github.com/tree-sitter/tree-sitter-embedded-template.git", rev = "1a538da253d73f896b9f6c0c7d79cda58791ac5c" }
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "ad1043283b1f9daf4aad381b6a81f18a5a27fe7e" }
tree-sitter-embedded-template = { git = "https://github.com/tree-sitter/tree-sitter-embedded-template.git", rev = "a13085849cf69e2401ec44e38cffc3d73f22f3df" }
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "7a1921bcfd90e3a04c1ad011059087aaf0168dd4" }

View File

@@ -1,3 +1,7 @@
## 0.5.1
No user-facing changes.
## 0.5.0
### Major Analysis Improvements

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Ruby 3.2: anonymous rest and keyword rest arguments can now be passed as arguments, instead of just used in method parameters.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Access to headers stored in the `env` of Rack requests is now recognized as a source of remote input.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Data flowing from the `locals` argument of a Rails `render` call is now tracked to uses of that data in an associated view.

View File

@@ -0,0 +1,3 @@
## 0.5.1
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.5.0
lastReleaseVersion: 0.5.1

View File

@@ -16,6 +16,7 @@ private import codeql.ruby.frameworks.ActiveSupport
private import codeql.ruby.frameworks.Archive
private import codeql.ruby.frameworks.Arel
private import codeql.ruby.frameworks.GraphQL
private import codeql.ruby.frameworks.Rack
private import codeql.ruby.frameworks.Rails
private import codeql.ruby.frameworks.Railties
private import codeql.ruby.frameworks.Stdlib

View File

@@ -158,6 +158,27 @@ class AddExpr extends BinaryArithmeticOperation, TAddExpr {
final override string getAPrimaryQlClass() { result = "AddExpr" }
}
/**
* A series of add expressions, e.g. `1 + 2 + 3`.
* This class is used to represent the root of such a series, and
* the `getALeaf` predicate can be used to get the leaf nodes.
*/
class AddExprRoot extends AddExpr {
AddExprRoot() { not this.getParent() instanceof AddExpr }
private AstNode getALeafOrAdd() {
result = this.getAChild()
or
result = this.getALeafOrAdd().(AddExpr).getAChild()
}
/** Gets a leaf node of this add expression. */
AstNode getALeaf() {
result = this.getALeafOrAdd() and
not result instanceof AddExpr
}
}
/**
* A subtract expression.
* ```rb

View File

@@ -181,7 +181,10 @@ class HashSplatParameter extends NamedParameter, THashSplatParameter {
final override string getAPrimaryQlClass() { result = "HashSplatParameter" }
final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g.getName()) }
final override LocalVariable getVariable() {
result = TLocalVariableReal(_, _, g.getName()) or
result = TLocalVariableSynth(this, 0)
}
final override string toString() {
result = "**" + this.getName()
@@ -307,7 +310,10 @@ class SplatParameter extends NamedParameter, TSplatParameter {
final override string getAPrimaryQlClass() { result = "SplatParameter" }
final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g.getName()) }
final override LocalVariable getVariable() {
result = TLocalVariableReal(_, _, g.getName()) or
result = TLocalVariableSynth(this, 0)
}
final override string toString() {
result = "*" + this.getName()

View File

@@ -36,7 +36,7 @@ class LocalVariable extends Variable, TLocalVariable {
/** Gets the access where this local variable is first introduced. */
VariableAccess getDefiningAccess() {
result = this.(LocalVariableReal).getDefiningAccessImpl() or
synthChild(any(BlockParameter p | this = p.getVariable()), 0, result)
synthChild(any(NamedParameter p | this = p.getVariable()), 0, result)
}
/**
@@ -120,7 +120,7 @@ class VariableAccess extends Expr instanceof VariableAccessImpl {
or
this = any(HashPattern p).getValue(_)
or
synthChild(any(BlockParameter p), 0, this)
synthChild(any(NamedParameter p), 0, this)
}
}

View File

@@ -42,7 +42,10 @@ class SplatExprReal extends UnaryOperationImpl, TSplatExprReal {
final override string getOperatorImpl() { result = "*" }
final override Expr getOperandImpl() { toGenerated(result) = g.getChild() }
final override Expr getOperandImpl() {
toGenerated(result) = g.getChild() or
synthChild(this, 0, result)
}
}
class SplatExprSynth extends UnaryOperationImpl, TSplatExprSynth {
@@ -56,7 +59,10 @@ class HashSplatExprImpl extends UnaryOperationImpl, THashSplatExpr {
HashSplatExprImpl() { this = THashSplatExpr(g) }
final override Expr getOperandImpl() { toGenerated(result) = g.getChild() }
final override Expr getOperandImpl() {
toGenerated(result) = g.getChild() or
synthChild(this, 0, result)
}
final override string getOperatorImpl() { result = "**" }
}

View File

@@ -1317,46 +1317,62 @@ private module ImplicitHashValueSynthesis {
/**
* ```rb
* def foo(&)
* bar(&)
* def foo(*, **, &)
* bar(*, **, &)
* end
* ```
* desugars to,
* ```rb
* def foo(&__synth_0)
* bar(&__synth_0)
* def foo(*__synth_0, **__synth_1, &__synth_2)
* bar(*__synth_0, **__synth_1, &__synth_2)
* end
* ```
*/
private module AnonymousBlockParameterSynth {
private BlockParameter anonymousBlockParameter() {
private module AnonymousParameterSynth {
private class AnonymousParameter = TBlockParameter or THashSplatParameter or TSplatParameter;
private class AnonymousArgument = TBlockArgument or THashSplatExpr or TSplatExpr;
private AnonymousParameter anonymousParameter() {
exists(Ruby::BlockParameter p | not exists(p.getName()) and toGenerated(result) = p)
or
exists(Ruby::SplatParameter p | not exists(p.getName()) and toGenerated(result) = p)
or
exists(Ruby::HashSplatParameter p | not exists(p.getName()) and toGenerated(result) = p)
}
private BlockArgument anonymousBlockArgument() {
private AnonymousArgument anonymousArgument() {
exists(Ruby::BlockArgument p | not exists(p.getChild()) and toGenerated(result) = p)
or
exists(Ruby::SplatArgument p | not exists(p.getChild()) and toGenerated(result) = p)
or
exists(Ruby::HashSplatArgument p | not exists(p.getChild()) and toGenerated(result) = p)
}
private class AnonymousBlockParameterSynthesis extends Synthesis {
private class AnonymousParameterSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child) {
i = 0 and
parent = anonymousBlockParameter() and
parent = anonymousParameter() and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(parent, 0)))
}
final override predicate localVariable(AstNode n, int i) {
n = anonymousBlockParameter() and i = 0
}
final override predicate localVariable(AstNode n, int i) { n = anonymousParameter() and i = 0 }
}
private class AnonymousBlockArgumentSynthesis extends Synthesis {
private class AnonymousArgumentSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child) {
i = 0 and
parent = anonymousBlockArgument() and
exists(BlockParameter param |
param = anonymousBlockParameter() and
parent = anonymousArgument() and
exists(AnonymousParameter param |
param = anonymousParameter() and
scopeOf(toGenerated(parent)).getEnclosingMethod() = scopeOf(toGenerated(param)) and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(param, 0)))
|
param instanceof TBlockParameter and parent instanceof TBlockArgument
or
param instanceof TSplatParameter and parent instanceof TSplatExpr
or
param instanceof THashSplatParameter and parent instanceof THashSplatExpr
)
}
}

View File

@@ -875,10 +875,10 @@ module Ruby {
final override string getAPrimaryQlClass() { result = "HashSplatArgument" }
/** Gets the child of this node. */
final UnderscoreArg getChild() { ruby_hash_splat_argument_def(this, result) }
final UnderscoreArg getChild() { ruby_hash_splat_argument_child(this, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() { ruby_hash_splat_argument_def(this, result) }
final override AstNode getAFieldOrChild() { ruby_hash_splat_argument_child(this, result) }
}
/** A class representing `hash_splat_nil` tokens. */
@@ -1572,10 +1572,10 @@ module Ruby {
final override string getAPrimaryQlClass() { result = "SplatArgument" }
/** Gets the child of this node. */
final UnderscoreArg getChild() { ruby_splat_argument_def(this, result) }
final UnderscoreArg getChild() { ruby_splat_argument_child(this, result) }
/** Gets a field or child node of this node. */
final override AstNode getAFieldOrChild() { ruby_splat_argument_def(this, result) }
final override AstNode getAFieldOrChild() { ruby_splat_argument_child(this, result) }
}
/** A class representing `splat_parameter` nodes. */

View File

@@ -30,6 +30,8 @@ module SummaryComponent {
predicate withContent = SC::withContent/1;
class SyntheticGlobal = SC::SyntheticGlobal;
/** Gets a summary component that represents a receiver. */
SummaryComponent receiver() { result = argument(any(ParameterPosition pos | pos.isSelf())) }
@@ -137,7 +139,7 @@ abstract class SummarizedCallable extends LibraryCallable, Impl::Public::Summari
DataFlow::ParameterNode getParameter(string s) {
exists(ParameterPosition pos |
DataFlowImplCommon::parameterNode(result, TLibraryCallable(this), pos) and
s = getParameterPositionCsv(pos)
s = getParameterPosition(pos)
)
}
}

View File

@@ -876,9 +876,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
PrevStage::readStepCand(node1, _, _, config)
}
bindingset[ap, c]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
hasHeadContent(ap, c)
}
pragma[nomagic]
@@ -1731,8 +1735,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1905,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1927,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -3749,8 +3753,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4216,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
}
pragma[nomagic]
@@ -4230,19 +4232,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
}
/**

View File

@@ -876,9 +876,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
PrevStage::readStepCand(node1, _, _, config)
}
bindingset[ap, c]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
hasHeadContent(ap, c)
}
pragma[nomagic]
@@ -1731,8 +1735,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1905,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1927,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -3749,8 +3753,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4216,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
}
pragma[nomagic]
@@ -4230,19 +4232,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
}
/**

View File

@@ -45,6 +45,16 @@ module Consistency {
) {
none()
}
/** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodeAtPosition`. */
predicate uniqueParameterNodeAtPositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
none()
}
/** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodePosition`. */
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
none()
}
}
private class RelevantNode extends Node {
@@ -101,9 +111,7 @@ module Consistency {
exists(int c |
c =
strictcount(Node n |
not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) and
not n.hasLocationInfo(_, _, _, _, _) and
not any(ConsistencyConfiguration conf).missingLocationExclude(n)
) and
msg = "Nodes without location: " + c
@@ -248,6 +256,7 @@ module Consistency {
query predicate uniqueParameterNodeAtPosition(
DataFlowCallable c, ParameterPosition pos, Node p, string msg
) {
not any(ConsistencyConfiguration conf).uniqueParameterNodeAtPositionExclude(c, pos, p) and
isParameterNode(p, c, pos) and
not exists(unique(Node p0 | isParameterNode(p0, c, pos))) and
msg = "Parameters with overlapping positions."
@@ -256,6 +265,7 @@ module Consistency {
query predicate uniqueParameterNodePosition(
DataFlowCallable c, ParameterPosition pos, Node p, string msg
) {
not any(ConsistencyConfiguration conf).uniqueParameterNodePositionExclude(c, pos, p) and
isParameterNode(p, c, pos) and
not exists(unique(ParameterPosition pos0 | isParameterNode(p, c, pos0))) and
msg = "Parameter node with multiple positions."

View File

@@ -876,9 +876,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
PrevStage::readStepCand(node1, _, _, config)
}
bindingset[ap, c]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
hasHeadContent(ap, c)
}
pragma[nomagic]
@@ -1731,8 +1735,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1905,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1927,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -3749,8 +3753,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4216,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
}
pragma[nomagic]
@@ -4230,19 +4232,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
}
/**

View File

@@ -876,9 +876,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
PrevStage::readStepCand(node1, _, _, config)
}
bindingset[ap, c]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
hasHeadContent(ap, c)
}
pragma[nomagic]
@@ -1731,8 +1735,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1905,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1927,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -3749,8 +3753,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4216,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
}
pragma[nomagic]
@@ -4230,19 +4232,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
}
/**

View File

@@ -876,9 +876,9 @@ private module Stage1 implements StageSig {
pragma[nomagic]
private predicate revFlowOut(ReturnPosition pos, Configuration config) {
exists(DataFlowCall call, NodeEx out |
exists(NodeEx out |
revFlow(out, _, config) and
viableReturnPosOutNodeCandFwd1(call, pos, out, config)
viableReturnPosOutNodeCandFwd1(_, pos, out, config)
)
}
@@ -1487,6 +1487,10 @@ private module MkStage<StageSig PrevStage> {
PrevStage::readStepCand(node1, _, _, config)
}
bindingset[ap, c]
pragma[inline_late]
private predicate hasHeadContent(Ap ap, Content c) { getHeadContent(ap) = c }
pragma[nomagic]
private predicate fwdFlowRead(
Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc,
@@ -1494,7 +1498,7 @@ private module MkStage<StageSig PrevStage> {
) {
fwdFlowRead0(node1, state, cc, summaryCtx, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
hasHeadContent(ap, c)
}
pragma[nomagic]
@@ -1731,8 +1735,8 @@ private module MkStage<StageSig PrevStage> {
)
or
// flow through a callable
exists(DataFlowCall call, ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config)
)
or
@@ -1901,8 +1905,8 @@ private module MkStage<StageSig PrevStage> {
pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) {
exists(RetNodeEx ret, ReturnPosition pos |
returnFlowsThrough(ret, pos, _, _, p, ap, _, config) and
exists(ReturnPosition pos |
returnFlowsThrough(_, pos, _, _, p, ap, _, config) and
parameterFlowsThroughRev(p, ap, pos, _, config)
)
}
@@ -1923,8 +1927,8 @@ private module MkStage<StageSig PrevStage> {
DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp,
Ap ap, Configuration config
) {
exists(ParamNodeEx p, ReturnPosition pos, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, pos, returnAp, ap, innerReturnAp, config) and
exists(ParamNodeEx p, Ap innerReturnAp |
revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and
flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config)
)
}
@@ -3749,8 +3753,8 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret |
pathNode(mid, ret, state, cc, sc, ap, config, _) and
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind)
@@ -4212,17 +4216,15 @@ private module FlowExploration {
ap = TRevPartialNil() and
exists(config.explorationLimit())
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentEx(node, ap.getHead()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
}
pragma[nomagic]
@@ -4230,19 +4232,17 @@ private module FlowExploration {
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
)
partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
not stateBarrier(node, state, config) and
not clearsContentEx(node, ap.getHead().getContent()) and
(
notExpectsContent(node) or
expectsContentEx(node, ap.getHead().getContent())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
else any()
}
/**

View File

@@ -364,8 +364,8 @@ private module Cached {
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
or
// Flow into phi node from read
exists(SsaImpl::DefinitionExt def, CfgNodes::ExprCfgNode exprFrom |
LocalFlow::localFlowSsaInputFromRead(exprFrom, def, nodeTo)
exists(CfgNodes::ExprCfgNode exprFrom |
LocalFlow::localFlowSsaInputFromRead(exprFrom, _, nodeTo)
|
exprFrom = nodeFrom.asExpr() and
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
@@ -410,8 +410,8 @@ private module Cached {
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
or
// Flow into phi node from read
exists(SsaImpl::DefinitionExt def, CfgNodes::ExprCfgNode exprFrom |
LocalFlow::localFlowSsaInputFromRead(exprFrom, def, nodeTo) and
exists(CfgNodes::ExprCfgNode exprFrom |
LocalFlow::localFlowSsaInputFromRead(exprFrom, _, nodeTo) and
exprFrom = [nodeFrom.asExpr(), nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr()]
)
}
@@ -893,8 +893,8 @@ private module ArgumentNodes {
(
this.asExpr() = call.getBlock()
or
exists(CfgNodes::ExprCfgNode arg, int n |
arg = call.getArgument(n) and
exists(CfgNodes::ExprCfgNode arg |
arg = call.getAnArgument() and
this.asExpr() = arg and
arg.getExpr() instanceof BlockArgument
)

View File

@@ -1002,6 +1002,9 @@ class CallableNode extends ExprNode {
/** Gets the `n`th positional parameter. */
ParameterNode getParameter(int n) { this.getParameterPosition(result).isPositional(n) }
/** Gets the number of positional parameters of this callable. */
final int getNumberOfParameters() { result = count(this.getParameter(_)) }
/** Gets the keyword parameter of the given name. */
ParameterNode getKeywordParameter(string name) {
this.getParameterPosition(result).isKeyword(name)

View File

@@ -39,6 +39,11 @@ module Public {
)
or
exists(ReturnKind rk | this = TReturnSummaryComponent(rk) and result = "return (" + rk + ")")
or
exists(SummaryComponent::SyntheticGlobal sg |
this = TSyntheticGlobalSummaryComponent(sg) and
result = "synthetic global (" + sg + ")"
)
}
}
@@ -159,24 +164,24 @@ module Public {
SummaryComponentStack return(ReturnKind rk) { result = singleton(SummaryComponent::return(rk)) }
}
private predicate noComponentSpecificCsv(SummaryComponent sc) {
not exists(getComponentSpecificCsv(sc))
private predicate noComponentSpecific(SummaryComponent sc) {
not exists(getComponentSpecific(sc))
}
/** Gets a textual representation of this component used for flow summaries. */
private string getComponentCsv(SummaryComponent sc) {
result = getComponentSpecificCsv(sc)
private string getComponent(SummaryComponent sc) {
result = getComponentSpecific(sc)
or
noComponentSpecificCsv(sc) and
noComponentSpecific(sc) and
(
exists(ArgumentPosition pos |
sc = TParameterSummaryComponent(pos) and
result = "Parameter[" + getArgumentPositionCsv(pos) + "]"
result = "Parameter[" + getArgumentPosition(pos) + "]"
)
or
exists(ParameterPosition pos |
sc = TArgumentSummaryComponent(pos) and
result = "Argument[" + getParameterPositionCsv(pos) + "]"
result = "Argument[" + getParameterPosition(pos) + "]"
)
or
sc = TReturnSummaryComponent(getReturnValueKind()) and result = "ReturnValue"
@@ -184,16 +189,16 @@ module Public {
}
/** Gets a textual representation of this stack used for flow summaries. */
string getComponentStackCsv(SummaryComponentStack stack) {
string getComponentStack(SummaryComponentStack stack) {
exists(SummaryComponent head, SummaryComponentStack tail |
head = stack.head() and
tail = stack.tail() and
result = getComponentStackCsv(tail) + "." + getComponentCsv(head)
result = getComponentStack(tail) + "." + getComponent(head)
)
or
exists(SummaryComponent c |
stack = TSingletonSummaryComponentStack(c) and
result = getComponentCsv(c)
result = getComponent(c)
)
}
@@ -241,15 +246,19 @@ module Public {
}
/**
* Holds if the summary is auto generated and not manually generated.
* Holds if all the summaries that apply to `this` are auto generated and not manually created.
*/
predicate isAutoGenerated() { none() }
final predicate isAutoGenerated() { this.hasProvenance("generated") and not this.isManual() }
/**
* Holds if the summary has the given provenance where `true` is
* `generated` and `false` is `manual`.
* Holds if there exists a manual summary that applies to `this`.
*/
predicate hasProvenance(boolean generated) { none() }
final predicate isManual() { this.hasProvenance("manual") }
/**
* Holds if there exists a summary that applies to `this` that has provenance `provenance`.
*/
predicate hasProvenance(string provenance) { none() }
}
/** A callable where there is no flow via the callable. */
@@ -257,15 +266,19 @@ module Public {
NeutralCallable() { neutralElement(this, _) }
/**
* Holds if the neutral is auto generated.
* Holds if the neutral is auto generated.
*/
predicate isAutoGenerated() { neutralElement(this, true) }
predicate isAutoGenerated() { neutralElement(this, "generated") }
/**
* Holds if the neutral has the given provenance where `true` is
* `generated` and `false` is `manual`.
* Holds if there exists a manual neutral that applies to `this`.
*/
predicate hasProvenance(boolean generated) { neutralElement(this, generated) }
final predicate isManual() { this.hasProvenance("manual") }
/**
* Holds if the neutral has provenance `provenance`.
*/
predicate hasProvenance(string provenance) { neutralElement(this, provenance) }
}
}
@@ -580,10 +593,8 @@ module Private {
head = TWithContentSummaryComponent(cont)
)
or
exists(ContentSet cont |
head = TWithoutContentSummaryComponent(cont) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
)
head = TWithoutContentSummaryComponent(_) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
@@ -658,8 +669,8 @@ module Private {
/** Holds if summary node `ret` is a return node of kind `rk`. */
predicate summaryReturnNode(Node ret, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s |
ret = summaryNodeOutputState(callable, s) and
exists(SummaryComponentStack s |
ret = summaryNodeOutputState(_, s) and
s = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
)
}
@@ -999,12 +1010,12 @@ module Private {
private predicate relevantSummaryElementGenerated(
AccessPath inSpec, AccessPath outSpec, string kind
) {
summaryElement(this, inSpec, outSpec, kind, true) and
not summaryElement(this, _, _, _, false)
summaryElement(this, inSpec, outSpec, kind, "generated") and
not summaryElement(this, _, _, _, "manual")
}
private predicate relevantSummaryElement(AccessPath inSpec, AccessPath outSpec, string kind) {
summaryElement(this, inSpec, outSpec, kind, false)
summaryElement(this, inSpec, outSpec, kind, "manual")
or
this.relevantSummaryElementGenerated(inSpec, outSpec, kind)
}
@@ -1023,10 +1034,8 @@ module Private {
)
}
override predicate isAutoGenerated() { this.relevantSummaryElementGenerated(_, _, _) }
override predicate hasProvenance(boolean generated) {
summaryElement(this, _, _, _, generated)
override predicate hasProvenance(string provenance) {
summaryElement(this, _, _, _, provenance)
}
}
@@ -1213,8 +1222,8 @@ module Private {
c.relevantSummary(input, output, preservesValue) and
csv =
c.getCallableCsv() // Callable information
+ getComponentStackCsv(input) + ";" // input
+ getComponentStackCsv(output) + ";" // output
+ getComponentStack(input) + ";" // input
+ getComponentStack(output) + ";" // output
+ renderKind(preservesValue) + ";" // kind
+ renderProvenance(c) // provenance
)

View File

@@ -49,25 +49,23 @@ DataFlowType getSyntheticGlobalType(SummaryComponent::SyntheticGlobal sg) { any(
/**
* Holds if an external flow summary exists for `c` with input specification
* `input`, output specification `output`, kind `kind`, and a flag `generated`
* stating whether the summary is autogenerated.
* `input`, output specification `output`, kind `kind`, and provenance `provenance`.
*/
predicate summaryElement(
FlowSummary::SummarizedCallable c, string input, string output, string kind, boolean generated
FlowSummary::SummarizedCallable c, string input, string output, string kind, string provenance
) {
exists(boolean preservesValue |
c.propagatesFlowExt(input, output, preservesValue) and
(if preservesValue = true then kind = "value" else kind = "taint") and
generated = false
provenance = "manual"
)
}
/**
* Holds if a neutral model exists for `c`, which means that there is no
* flow through `c`. The flag `generated` states whether the neutral model is autogenerated.
* Note. Neutral models have not been implemented for ruby.
* Holds if a neutral model exists for `c` with provenance `provenance`,
* which means that there is no flow through `c`.
*/
predicate neutralElement(FlowSummary::SummarizedCallable c, boolean generated) { none() }
predicate neutralElement(FlowSummary::SummarizedCallable c, string provenance) { none() }
bindingset[arg]
private SummaryComponent interpretElementArg(string arg) {
@@ -141,10 +139,10 @@ SummaryComponent interpretComponentSpecific(AccessPathToken c) {
}
/** Gets the textual representation of a summary component in the format used for flow summaries. */
string getComponentSpecificCsv(SummaryComponent sc) { none() }
string getComponentSpecific(SummaryComponent sc) { none() }
/** Gets the textual representation of a parameter position in the format used for flow summaries. */
string getParameterPositionCsv(ParameterPosition pos) {
string getParameterPosition(ParameterPosition pos) {
exists(int i |
pos.isPositional(i) and
result = i.toString()
@@ -174,7 +172,7 @@ string getParameterPositionCsv(ParameterPosition pos) {
}
/** Gets the textual representation of an argument position in the format used for flow summaries. */
string getArgumentPositionCsv(ArgumentPosition pos) {
string getArgumentPosition(ArgumentPosition pos) {
pos.isSelf() and result = "self"
or
pos.isBlock() and result = "block"
@@ -207,17 +205,15 @@ NormalReturnKind getReturnValueKind() { any() }
private module UnusedSourceSinkInterpretation {
/**
* Holds if an external source specification exists for `n` with output specification
* `output`, kind `kind`, and a flag `generated` stating whether the source specification is
* autogenerated.
* `output`, kind `kind`, and provenance `provenance`.
*/
predicate sourceElement(AstNode n, string output, string kind, boolean generated) { none() }
predicate sourceElement(AstNode n, string output, string kind, string provenance) { none() }
/**
* Holds if an external sink specification exists for `n` with input specification
* `input`, kind `kind` and a flag `generated` stating whether the sink specification is
* autogenerated.
* `input`, kind `kind` and provenance `provenance`.
*/
predicate sinkElement(AstNode n, string input, string kind, boolean generated) { none() }
predicate sinkElement(AstNode n, string input, string kind, string provenance) { none() }
class SourceOrSinkElement = AstNode;

View File

@@ -301,27 +301,39 @@ private module Request {
override Http::Server::RequestInputKind getKind() { result = Http::Server::bodyInputKind() }
}
/**
* A method call on `request` which returns the rack env.
* This is a hash containing all the information about the request. Values
* under keys starting with `HTTP_` are user-controlled.
*/
private class EnvCall extends RequestMethodCall {
EnvCall() { this.getMethodName() = ["env", "filtered_env"] }
}
private module Env {
abstract private class Env extends DataFlow::LocalSourceNode { }
/**
* A read of a user-controlled parameter from the request env.
*/
private class EnvHttpAccess extends DataFlow::CallNode, Http::Server::RequestInputAccess::Range {
EnvHttpAccess() {
this = any(EnvCall c).getAMethodCall("[]") and
this.getArgument(0).getConstantValue().getString().regexpMatch("^HTTP_.+")
/**
* A method call on `request` which returns the rack env.
* This is a hash containing all the information about the request. Values
* under keys starting with `HTTP_` are user-controlled.
*/
private class RequestEnvCall extends DataFlow::CallNode, Env {
RequestEnvCall() { this.getMethodName() = ["env", "filtered_env"] }
}
override Http::Server::RequestInputKind getKind() { result = Http::Server::headerInputKind() }
private import codeql.ruby.frameworks.Rack
override string getSourceType() { result = "ActionDispatch::Request#env[]" }
private class RackEnv extends Env {
RackEnv() { this = any(Rack::AppCandidate app).getEnv().getALocalUse() }
}
/**
* A read of a user-controlled parameter from the request env.
*/
private class EnvHttpAccess extends DataFlow::CallNode, Http::Server::RequestInputAccess::Range {
EnvHttpAccess() {
this = any(Env c).getAMethodCall("[]") and
exists(string key | key = this.getArgument(0).getConstantValue().getString() |
key.regexpMatch("^HTTP_.+") or key = "PATH_INFO"
)
}
override Http::Server::RequestInputKind getKind() { result = Http::Server::headerInputKind() }
override string getSourceType() { result = "ActionDispatch::Request#env[]" }
}
}
}

View File

@@ -0,0 +1,48 @@
/**
* Provides modeling for the Rack library.
*/
private import codeql.ruby.controlflow.CfgNodes::ExprNodes
private import codeql.ruby.DataFlow
private import codeql.ruby.typetracking.TypeTracker
/**
* Provides modeling for the Rack library.
*/
module Rack {
/**
* A class that may be a rack application.
* This is a class that has a `call` method that takes a single argument
* (traditionally called `env`) and returns a rack-compatible response.
*/
class AppCandidate extends DataFlow::ClassNode {
private DataFlow::MethodNode call;
AppCandidate() {
call = this.getInstanceMethod("call") and
call.getNumberOfParameters() = 1 and
call.getReturn() = trackRackResponse()
}
/**
* Gets the environment of the request, which is the lone parameter to the `call` method.
*/
DataFlow::ParameterNode getEnv() { result = call.getParameter(0) }
}
private predicate isRackResponse(DataFlow::Node r) {
// [status, headers, body]
r.asExpr().(ArrayLiteralCfgNode).getNumberOfArguments() = 3
}
private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t) {
t.start() and
isRackResponse(result)
or
exists(TypeTracker t2 | result = trackRackResponse(t2).track(t2, t))
}
private DataFlow::Node trackRackResponse() {
trackRackResponse(TypeTracker::end()).flowsTo(result)
}
}

View File

@@ -10,6 +10,43 @@ private import codeql.ruby.frameworks.ActiveStorage
private import codeql.ruby.frameworks.internal.Rails
private import codeql.ruby.ApiGraphs
private import codeql.ruby.security.OpenSSL
private import codeql.ruby.dataflow.FlowSummary
/** Provides utility predicates for extracting information from calls to `render`. */
private module RenderCallUtils {
private Expr getTemplatePathArgument(MethodCall renderCall) {
// TODO: support other ways of specifying paths (e.g. `file`)
result =
[renderCall.getKeywordArgument(["partial", "template", "action"]), renderCall.getArgument(0)]
}
private string getTemplatePathValue(MethodCall renderCall) {
result = getTemplatePathArgument(renderCall).getConstantValue().getStringlikeValue()
}
// everything up to and including the final slash, but ignoring any leading slash
private string getSubPath(MethodCall renderCall) {
result = getTemplatePathValue(renderCall).regexpCapture("^/?(.*/)?(?:[^/]*?)$", 1)
}
// everything after the final slash, or the whole string if there is no slash
private string getBaseName(MethodCall renderCall) {
result = getTemplatePathValue(renderCall).regexpCapture("^/?(?:.*/)?([^/]*?)$", 1)
}
/**
* Gets the template file to be rendered by this render call, if any.
*/
ErbFile getTemplateFile(MethodCall renderCall) {
result.getTemplateName() = getBaseName(renderCall) and
result.getRelativePath().matches("%app/views/" + getSubPath(renderCall) + "%")
}
/**
* Gets the local variables passed as context to the renderer.
*/
HashLiteral getLocals(MethodCall renderCall) { result = renderCall.getKeywordArgument("locals") }
}
/**
* Provides classes for working with Rails.
@@ -38,37 +75,15 @@ module Rails {
* rendered content.
*/
class RenderCall extends MethodCall instanceof RenderCallImpl {
private Expr getTemplatePathArgument() {
// TODO: support other ways of specifying paths (e.g. `file`)
result = [this.getKeywordArgument(["partial", "template", "action"]), this.getArgument(0)]
}
private string getTemplatePathValue() {
result = this.getTemplatePathArgument().getConstantValue().getStringlikeValue()
}
// everything up to and including the final slash, but ignoring any leading slash
private string getSubPath() {
result = this.getTemplatePathValue().regexpCapture("^/?(.*/)?(?:[^/]*?)$", 1)
}
// everything after the final slash, or the whole string if there is no slash
private string getBaseName() {
result = this.getTemplatePathValue().regexpCapture("^/?(?:.*/)?([^/]*?)$", 1)
}
/**
* Gets the template file to be rendered by this call, if any.
*/
ErbFile getTemplateFile() {
result.getTemplateName() = this.getBaseName() and
result.getRelativePath().matches("%app/views/" + this.getSubPath() + "%")
}
ErbFile getTemplateFile() { result = RenderCallUtils::getTemplateFile(this) }
/**
* Get the local variables passed as context to the renderer
* Gets the local variables passed as context to the renderer.
*/
HashLiteral getLocals() { result = this.getKeywordArgument("locals") }
HashLiteral getLocals() { result = RenderCallUtils::getLocals(this) }
// TODO: implicit renders in controller actions
}
@@ -287,5 +302,92 @@ private class CookiesSameSiteProtectionSetting extends Settings::NillableStringl
result = "Unsetting 'SameSite' can disable same-site cookie restrictions in some browsers."
}
}
// TODO: initialization hooks, e.g. before_configuration, after_initialize...
// TODO: initializers
/** A synthetic global to represent the value passed to the `locals` argument of a render call for a specific ERB file. */
private class LocalAssignsHashSyntheticGlobal extends SummaryComponent::SyntheticGlobal {
private ErbFile erbFile;
private string id;
// Note that we can't use an actual `Rails::RenderCall` here due to problems with non-monotonic recursion
private MethodCall renderCall;
LocalAssignsHashSyntheticGlobal() {
this = "LocalAssignsHashSyntheticGlobal+" + id and
id = erbFile.getRelativePath() + "+" + renderCall.getLocation() and
renderCall.getMethodName() = "render" and
RenderCallUtils::getTemplateFile(renderCall) = erbFile
}
/** Gets the `ErbFile` which this locals hash is accessible from. */
ErbFile getErbFile() { result = erbFile }
/** Gets the identifier for this particular locals hash synthetic global. */
string getId() { result = id }
/** Gets a call to render that can write to this hash. */
Rails::RenderCall getARenderCall() { result = renderCall }
}
/** A summary for `render` calls linked to some specific ERB file. */
private class RenderLocalsSummary extends SummarizedCallable {
private LocalAssignsHashSyntheticGlobal glob;
RenderLocalsSummary() { this = "rails_render_locals()" + glob.getId() }
override Rails::RenderCall getACall() { result = glob.getARenderCall() }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "Argument[locals:]" and
output = "SyntheticGlobal[" + glob + "]" and
preservesValue = true
}
}
/** A summary for calls to `local_assigns` in a view to access a `render` call `locals` hash. */
private class AccessLocalsSummary extends SummarizedCallable {
private LocalAssignsHashSyntheticGlobal glob;
AccessLocalsSummary() { this = "rails_local_assigns()" + glob.getId() }
override MethodCall getACall() {
glob.getErbFile() = result.getLocation().getFile() and
result.getMethodName() = "local_assigns"
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "SyntheticGlobal[" + glob + "]" and
output = "ReturnValue" and
preservesValue = true
}
}
private string getAMethodNameFromErbFile(ErbFile f) {
result = any(MethodCall c | c.getLocation().getFile() = f).getMethodName()
}
private class AccessLocalsKeySummary extends SummarizedCallable {
private LocalAssignsHashSyntheticGlobal glob;
private string methodName;
AccessLocalsKeySummary() {
this = "rails_locals_key()" + glob.getId() + "#" + methodName and
methodName = getAMethodNameFromErbFile(glob.getErbFile()) and
// Limit method calls to those that could plausibly be a key in a `locals` hash argument
// TODO: this could be more precise but for problems using the dataflow library in this context
methodName =
any(HashLiteral l).getAKeyValuePair().getKey().getConstantValue().getStringlikeValue()
}
override MethodCall getACall() {
result.getLocation().getFile() = glob.getErbFile() and
result.getMethodName() = methodName and
result.getReceiver() instanceof SelfVariableReadAccess
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
input = "SyntheticGlobal[" + glob + "].Element[:" + methodName + "]" and
output = "ReturnValue" and
preservesValue = true
}
}

View File

@@ -96,7 +96,7 @@ private class LibXmlRubyXmlParserCall extends XmlParserCall::Range, DataFlow::Ca
or
// If the database contains a call to set `default_substitute_entities` to
// true, then we assume external entities are enabled for this call
exists(AssignExpr ae | enablesLibXmlDefaultEntitySubstitution(ae))
enablesLibXmlDefaultEntitySubstitution(_)
}
}

View File

@@ -224,10 +224,9 @@ private module Impl implements RegexTreeViewSig {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(int re_start, int re_end |
exists(int re_start |
this.componentHasLocationInfo(0, filepath, startline, re_start, _, _) and
this.componentHasLocationInfo(re.getNumberOfComponents() - 1, filepath, _, _, endline,
re_end) and
this.componentHasLocationInfo(re.getNumberOfComponents() - 1, filepath, _, _, endline, _) and
startcolumn = re_start + start and
endcolumn = re_start + end - 1
)

View File

@@ -993,10 +993,8 @@ abstract class RegExp extends Ast::StringlikeLiteral {
this.specialCharacter(end, y, ["$", "\\Z", "\\z"])
)
or
exists(int x |
this.lastPart(x, end) and
this.item(start, end)
)
this.lastPart(_, end) and
this.item(start, end)
or
exists(int y | this.lastPart(start, y) | this.qualifiedPart(start, end, y, _, _))
or

View File

@@ -0,0 +1,138 @@
/**
* Provides default sources, sinks and sanitizers for reasoning about
* code constructed from library input vulnerabilities, as
* well as extension points for adding your own.
*/
private import ruby
private import codeql.ruby.ApiGraphs
private import codeql.ruby.frameworks.core.Gem::Gem as Gem
private import codeql.ruby.Concepts as Concepts
/**
* Module containing sources, sinks, and sanitizers for code constructed from library input.
*/
module UnsafeCodeConstruction {
/** A source for code constructed from library input vulnerabilities. */
abstract class Source extends DataFlow::Node { }
/** An input parameter to a gem seen as a source. */
private class LibraryInputAsSource extends Source instanceof DataFlow::ParameterNode {
LibraryInputAsSource() {
this = Gem::getALibraryInput() and
not this.getName() = "code"
}
}
/** A sink for code constructed from library input vulnerabilities. */
abstract class Sink extends DataFlow::Node {
/**
* Gets the node where the unsafe code is executed.
*/
abstract DataFlow::Node getCodeSink();
/**
* Gets the type of sink.
*/
string getSinkType() { result = "code construction" }
}
/** Gets a node that is eventually executed as code at `codeExec`. */
DataFlow::Node getANodeExecutedAsCode(Concepts::CodeExecution codeExec) {
result = getANodeExecutedAsCode(TypeTracker::TypeBackTracker::end(), codeExec)
}
import codeql.ruby.typetracking.TypeTracker as TypeTracker
/** Gets a node that is eventually executed as code at `codeExec`, type-tracked with `t`. */
private DataFlow::LocalSourceNode getANodeExecutedAsCode(
TypeTracker::TypeBackTracker t, Concepts::CodeExecution codeExec
) {
t.start() and
result = codeExec.getCode().getALocalSource() and
codeExec.runsArbitraryCode() // methods like `Object.send` is benign here, because of the string-construction the attacker cannot control the entire method name
or
exists(TypeTracker::TypeBackTracker t2 |
result = getANodeExecutedAsCode(t2, codeExec).backtrack(t2, t)
)
}
/**
* A string constructed using a `.join(...)` call, where the resulting string ends up being executed as code.
*/
class ArrayJoin extends Sink {
Concepts::CodeExecution s;
ArrayJoin() {
exists(DataFlow::CallNode call |
call.getMethodName() = "join" and
call.getNumberOfArguments() = 1 and // any string. E.g. ";" or "\n".
call = getANodeExecutedAsCode(s) and
this = call.getReceiver()
)
}
override DataFlow::Node getCodeSink() { result = s }
override string getSinkType() { result = "array" }
}
/**
* A string constructed from a string-literal (e.g. `"foo #{sink}"`),
* where the resulting string ends up being executed as a code.
*/
class StringInterpolationAsSink extends Sink {
Concepts::CodeExecution s;
StringInterpolationAsSink() {
exists(Ast::StringlikeLiteral lit |
any(DataFlow::Node n | n.asExpr().getExpr() = lit) = getANodeExecutedAsCode(s) and
this.asExpr().getExpr() = lit.getComponent(_)
)
}
override DataFlow::Node getCodeSink() { result = s }
override string getSinkType() { result = "string interpolation" }
}
/**
* A component of a string-concatenation (e.g. `"foo " + sink`),
* where the resulting string ends up being executed as a code.
*/
class StringConcatAsSink extends Sink {
Concepts::CodeExecution s;
StringConcatAsSink() {
exists(Ast::AddExprRoot add |
any(DataFlow::Node n | n.asExpr().getExpr() = add) = getANodeExecutedAsCode(s) and
this.asExpr().getExpr() = add.getALeaf()
)
}
override DataFlow::Node getCodeSink() { result = s }
override string getSinkType() { result = "string concatenation" }
}
import codeql.ruby.security.TaintedFormatStringSpecific as TaintedFormat
/**
* A string constructed from a printf-style call,
* where the resulting string ends up being executed as a code.
*/
class TaintedFormatStringAsSink extends Sink {
Concepts::CodeExecution s;
TaintedFormatStringAsSink() {
exists(TaintedFormat::PrintfStyleCall call |
call = getANodeExecutedAsCode(s) and
this = [call.getFormatArgument(_), call.getFormatString()]
)
}
override DataFlow::Node getCodeSink() { result = s }
override string getSinkType() { result = "string format" }
}
}

View File

@@ -0,0 +1,49 @@
/**
* Provides a taint-tracking configuration for reasoning about code
* constructed from library input vulnerabilities.
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `UnsafeCodeConstructionCustomizations` should be imported instead.
*/
import codeql.ruby.DataFlow
import UnsafeCodeConstructionCustomizations::UnsafeCodeConstruction
private import codeql.ruby.TaintTracking
private import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for detecting code constructed from library input vulnerabilities.
*/
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeShellCommandConstruction" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) {
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier
}
// override to require the path doesn't have unmatched return steps
override DataFlow::FlowFeature getAFeature() {
result instanceof DataFlow::FeatureHasSourceCallContext
}
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
// if an array element gets tainted, then we treat the entire array as tainted
exists(DataFlow::CallNode call |
call.getMethodName() = ["<<", "push", "append"] and
call.getReceiver() = succ and
pred = call.getArgument(0) and
call.getNumberOfArguments() = 1
)
or
exists(DataFlow::CallNode call |
call.getMethodName() = "[]" and
succ = call and
pred = call.getArgument(_)
)
}
}

View File

@@ -0,0 +1,96 @@
/**
* Provides default sources, sinks and sanitizers for reasoning about
* HTML constructed from library input vulnerabilities, as
* well as extension points for adding your own.
*/
private import ruby
private import codeql.ruby.ApiGraphs
private import codeql.ruby.frameworks.core.Gem::Gem as Gem
/**
* Module containing sources, sinks, and sanitizers for HTML constructed from library input.
*/
module UnsafeHtmlConstruction {
/** A source for HTML constructed from library input vulnerabilities. */
abstract class Source extends DataFlow::Node { }
/** An input parameter to a gem seen as a source. */
private class LibraryInputAsSource extends Source instanceof DataFlow::ParameterNode {
LibraryInputAsSource() { this = Gem::getALibraryInput() }
}
/** A sink for HTML constructed from library input vulnerabilities. */
abstract class Sink extends DataFlow::Node {
/**
* Gets the node for the XSS sink the HTML flows to.
*/
abstract DataFlow::Node getXssSink();
/**
* Gets the type of sink.
*/
abstract string getSinkType();
}
private import codeql.ruby.security.XSS::ReflectedXss as ReflectedXss
/** Gets a node that eventually ends up in the XSS `sink`. */
private DataFlow::Node getANodeThatEndsInXssSink(ReflectedXss::Sink sink) {
result = getANodeThatEndsInXssSink(TypeTracker::TypeBackTracker::end(), sink)
}
private import codeql.ruby.typetracking.TypeTracker as TypeTracker
/** Gets a node that is eventually ends up in the XSS `sink`, type-tracked with `t`. */
private DataFlow::LocalSourceNode getANodeThatEndsInXssSink(
TypeTracker::TypeBackTracker t, ReflectedXss::Sink sink
) {
t.start() and
result = sink.getALocalSource()
or
exists(TypeTracker::TypeBackTracker t2 |
result = getANodeThatEndsInXssSink(t2, sink).backtrack(t2, t)
)
}
/**
* A component of a string-literal (e.g. `"foo #{sink}"`),
* where the resulting string ends up being used in an XSS sink.
*/
private class StringFormatAsSink extends Sink {
ReflectedXss::Sink s;
StringFormatAsSink() {
exists(Ast::StringlikeLiteral lit |
any(DataFlow::Node n | n.asExpr().getExpr() = lit) = getANodeThatEndsInXssSink(s) and
this.asExpr().getExpr() = lit.getComponent(_)
)
}
override DataFlow::Node getXssSink() { result = s }
override string getSinkType() { result = "string interpolation" }
}
private import codeql.ruby.security.TaintedFormatStringSpecific as TaintedFormat
/**
* An argument to a printf-style call,
* where the resulting string ends up being used in an XSS sink.
*/
private class TaintedFormatStringAsSink extends Sink {
ReflectedXss::Sink s;
TaintedFormatStringAsSink() {
exists(TaintedFormat::PrintfStyleCall call |
call = getANodeThatEndsInXssSink(s) and
this = [call.getFormatArgument(_), call.getFormatString()]
)
}
override DataFlow::Node getXssSink() { result = s }
override string getSinkType() { result = "string format" }
}
}

View File

@@ -0,0 +1,33 @@
/**
* Provides a taint-tracking configuration for reasoning about HTML
* constructed from library input vulnerabilities.
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `UnsafeHtmlConstructionCustomizations` should be imported instead.
*/
import codeql.ruby.DataFlow
import UnsafeHtmlConstructionCustomizations::UnsafeHtmlConstruction
private import codeql.ruby.TaintTracking
private import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for detecting unsafe HTML construction.
*/
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeHtmlConstruction" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) {
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier
}
// override to require the path doesn't have unmatched return steps
override DataFlow::FlowFeature getAFeature() {
result instanceof DataFlow::FeatureHasSourceCallContext
}
}

View File

@@ -67,7 +67,7 @@ module UnsafeShellCommandConstruction {
*/
class StringInterpolationAsSink extends Sink {
Concepts::SystemCommandExecution s;
Ast::StringLiteral lit;
Ast::StringlikeLiteral lit;
StringInterpolationAsSink() {
isUsedAsShellCommand(any(DataFlow::Node n | n.asExpr().getExpr() = lit), s) and
@@ -81,6 +81,26 @@ module UnsafeShellCommandConstruction {
override DataFlow::Node getStringConstruction() { result.asExpr().getExpr() = lit }
}
/**
* A component of a string-concatenation (e.g. `"foo " + sink`),
* where the resulting string ends up being executed as a shell command.
*/
class StringConcatAsSink extends Sink {
Concepts::SystemCommandExecution s;
Ast::AddExprRoot add;
StringConcatAsSink() {
isUsedAsShellCommand(any(DataFlow::Node n | n.asExpr().getExpr() = add), s) and
this.asExpr().getExpr() = add.getALeaf()
}
override DataFlow::Node getCommandExecution() { result = s }
override string describe() { result = "string concatenation" }
override DataFlow::Node getStringConstruction() { result.asExpr().getExpr() = add }
}
/**
* A string constructed using a `.join(" ")` call, where the resulting string ends up being executed as a shell command.
*/

View File

@@ -162,46 +162,6 @@ private module Shared {
erb = call.getLocation().getFile()
}
/**
* Holds if some render call passes `value` for `hashKey` in the `locals`
* argument, in ERB file `erb`.
*/
pragma[noinline]
private predicate renderCallLocals(string hashKey, Expr value, ErbFile erb) {
exists(Rails::RenderCall call, Pair kvPair |
call.getLocals().getAKeyValuePair() = kvPair and
kvPair.getValue() = value and
kvPair.getKey().getConstantValue().isStringlikeValue(hashKey) and
call.getTemplateFile() = erb
)
}
pragma[noinline]
private predicate isFlowFromLocals0(
CfgNodes::ExprNodes::ElementReferenceCfgNode refNode, string hashKey, ErbFile erb
) {
exists(DataFlow::Node argNode |
argNode.asExpr() = refNode.getArgument(0) and
refNode.getReceiver().getExpr().(MethodCall).getMethodName() = "local_assigns" and
argNode.getALocalSource().getConstantValue().isStringlikeValue(hashKey) and
erb = refNode.getFile()
)
}
private predicate isFlowFromLocals(DataFlow::Node node1, DataFlow::Node node2) {
exists(string hashKey, ErbFile erb |
// node1 is a `locals` argument to a render call...
renderCallLocals(hashKey, node1.asExpr().getExpr(), erb)
|
// node2 is an element reference against `local_assigns`
isFlowFromLocals0(node2.asExpr(), hashKey, erb)
or
// ...node2 is a "method call" to a "method" with `hashKey` as its name
// TODO: This may be a variable read in reality that we interpret as a method call
isMethodCall(node2.asExpr().getExpr(), hashKey, erb)
)
}
/**
* Holds if `action` contains an assignment of `value` to an instance
* variable named `name`, in ERB file `erb`.
@@ -227,9 +187,9 @@ private module Shared {
private predicate isFlowFromControllerInstanceVariable(DataFlow::Node node1, DataFlow::Node node2) {
// instance variables in the controller
exists(ActionControllerActionMethod action, string name, ErbFile template |
exists(string name, ErbFile template |
// match read to write on variable name
actionAssigns(action, name, node1.asExpr().getExpr(), template) and
actionAssigns(_, name, node1.asExpr().getExpr(), template) and
// propagate taint from assignment RHS expr to variable read access in view
isVariableReadAccess(node2.asExpr().getExpr(), name, template)
)
@@ -275,8 +235,6 @@ private module Shared {
* An additional step that is preserves dataflow in the context of XSS.
*/
predicate isAdditionalXssFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isFlowFromLocals(node1, node2)
or
isFlowFromControllerInstanceVariable(node1, node2)
or
isFlowIntoHelperMethod(node1, node2)

View File

@@ -1,5 +1,5 @@
name: codeql/ruby-all
version: 0.5.1-dev
version: 0.5.2-dev
groups: ruby
extractor: ruby
dbscheme: ruby.dbscheme

View File

@@ -661,9 +661,13 @@ ruby_hash_pattern_def(
unique int id: @ruby_hash_pattern
);
ruby_hash_splat_argument_child(
unique int ruby_hash_splat_argument: @ruby_hash_splat_argument ref,
unique int child: @ruby_underscore_arg ref
);
ruby_hash_splat_argument_def(
unique int id: @ruby_hash_splat_argument,
int child: @ruby_underscore_arg ref
unique int id: @ruby_hash_splat_argument
);
ruby_hash_splat_parameter_name(
@@ -1112,9 +1116,13 @@ ruby_singleton_method_def(
int object: @ruby_singleton_method_object_type ref
);
ruby_splat_argument_child(
unique int ruby_splat_argument: @ruby_splat_argument ref,
unique int child: @ruby_underscore_arg ref
);
ruby_splat_argument_def(
unique int id: @ruby_splat_argument,
int child: @ruby_underscore_arg ref
unique int id: @ruby_splat_argument
);
ruby_splat_parameter_name(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
description: Update grammar
compatibility: full
ruby_splat_argument_def.rel: reorder ruby_splat_argument_def.rel ( int id, int child) id
ruby_splat_argument_child.rel: reorder ruby_splat_argument_def.rel ( int id, int child) id child
ruby_hash_splat_argument_def.rel: reorder ruby_hash_splat_argument_def.rel ( int id, int child) id
ruby_hash_splat_argument_child.rel: reorder ruby_hash_splat_argument_def.rel ( int id, int child) id child

View File

@@ -1,3 +1,13 @@
## 0.5.1
### New Queries
* Added a new query, `rb/unsafe-code-construction`, to detect libraries that unsafely construct code from their inputs.
### Minor Analysis Improvements
* The `rb/unsafe-deserialization` query now recognizes input from STDIN as a source.
## 0.5.0
### New Queries

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* Added a new query, `rb/html-constructed-from-input`, to detect libraries that unsafely construct HTML from their inputs.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The `rb/unsafe-deserialization` query now recognizes input from STDIN as a source.

View File

@@ -0,0 +1,9 @@
## 0.5.1
### New Queries
* Added a new query, `rb/unsafe-code-construction`, to detect libraries that unsafely construct code from their inputs.
### Minor Analysis Improvements
* The `rb/unsafe-deserialization` query now recognizes input from STDIN as a source.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.5.0
lastReleaseVersion: 0.5.1

View File

@@ -0,0 +1,4 @@
- description: Extended and experimental security queries for Ruby
- queries: .
- apply: security-experimental-selectors.yml
from: codeql/suite-helpers

View File

@@ -7,6 +7,7 @@
* @precision medium
* @id rb/user-controlled-bypass
* @tags security
* experimental
* external/cwe/cwe-807
* external/cwe/cwe-290
*/

View File

@@ -6,7 +6,9 @@
* @security-severity 7.8
* @precision medium
* @id rb/user-controlled-file-decompression
* @tags security external/cwe/cwe-409
* @tags security
* experimental
* external/cwe/cwe-409
*/
import codeql.ruby.AST

View File

@@ -5,6 +5,7 @@
* @problem.severity warning
* @precision high
* @tags security
* experimental
* @id rb/improper-memoization
*/

View File

@@ -7,6 +7,7 @@
* @precision low
* @id rb/manually-checking-http-verb
* @tags security
* experimental
*/
import codeql.ruby.AST

View File

@@ -7,6 +7,7 @@
* @precision medium
* @id rb/weak-params
* @tags security
* experimental
*/
import codeql.ruby.AST

View File

@@ -1,5 +1,5 @@
name: codeql/ruby-queries
version: 0.5.1-dev
version: 0.5.2-dev
groups:
- ruby
- queries

View File

@@ -0,0 +1,73 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
When a library function dynamically constructs HTML in a potentially unsafe
way, then it's important to document to clients of the library that the function
should only be used with trusted inputs.
If the function is not documented as being potentially unsafe, then a client
may inadvertently use inputs containing unsafe HTML fragments, and thereby leave
the client vulnerable to cross-site scripting attacks.
</p>
</overview>
<recommendation>
<p>
Document all library functions that can lead to cross-site scripting
attacks, and guard against unsafe inputs where dynamic HTML
construction is not intended.
</p>
</recommendation>
<example>
<p>
The following example has a library function that renders a boldface name
by creating a string containing a <code>&lt;b&gt;</code> with the name
embedded in it.
</p>
<sample src="examples/unsafe-html-construction.rb" />
<p>
This library function, however, does not escape unsafe HTML, and a client
that calls the function with user-supplied input may be vulnerable to
cross-site scripting attacks.
</p>
<p>
The library could either document that this function should not be used
with unsafe inputs, or escape the input before embedding it in the
HTML fragment.
</p>
<sample src="examples/unsafe-html-construction_safe.rb" />
</example>
<references>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet">DOM based
XSS Prevention Cheat Sheet</a>.
</li>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet">XSS
(Cross Site Scripting) Prevention Cheat Sheet</a>.
</li>
<li>
OWASP
<a href="https://www.owasp.org/index.php/DOM_Based_XSS">DOM Based XSS</a>.
</li>
<li>
OWASP
<a href="https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting">Types of Cross-Site
Scripting</a>.
</li>
<li>
Wikipedia: <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">Cross-site scripting</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,22 @@
/**
* @name Unsafe HTML constructed from library input
* @description Using externally controlled strings to construct HTML might allow a malicious
* user to perform a cross-site scripting attack.
* @kind path-problem
* @problem.severity error
* @security-severity 6.1
* @precision high
* @id rb/html-constructed-from-input
* @tags security
* external/cwe/cwe-079
* external/cwe/cwe-116
*/
import codeql.ruby.security.UnsafeHtmlConstructionQuery
import DataFlow::PathGraph
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where cfg.hasFlowPath(source, sink) and sink.getNode() = sinkNode
select sinkNode, source, sink,
"This " + sinkNode.getSinkType() + " which depends on $@ might later allow $@.", source.getNode(),
"library input", sinkNode.getXssSink(), "cross-site scripting"

View File

@@ -0,0 +1,6 @@
class UsersController < ActionController::Base
# BAD - create a user description, where the name is not escaped
def create_user_description (name)
"<b>#{name}</b>".html_safe
end
end

View File

@@ -0,0 +1,6 @@
class UsersController < ActionController::Base
# Good - create a user description, where the name is escaped
def create_user_description (name)
"<b>#{ERB::Util.html_escape(name)}</b>".html_safe
end
end

View File

@@ -0,0 +1,111 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
When a library function dynamically constructs code in a potentially unsafe way,
it's important to document to clients of the library that the function should only be
used with trusted inputs.
If the function is not documented as being potentially unsafe, then a client may
incorrectly use inputs containing unsafe code fragments, and thereby leave the
client vulnerable to code-injection attacks.
</p>
</overview>
<recommendation>
<p>
Properly document library functions that construct code from unsanitized
inputs, or avoid constructing code in the first place.
</p>
</recommendation>
<example>
<p>
The following example shows two methods implemented using <code>eval</code>: a simple
deserialization routine and a getter method.
If untrusted inputs are used with these methods,
then an attacker might be able to execute arbitrary code on the system.
</p>
<sample src="examples/UnsafeCodeConstruction.rb" />
<p>
To avoid this problem, either properly document that the function is potentially
unsafe, or use an alternative solution such as <code>JSON.parse</code> or another library
that does not allow arbitrary code to be executed.
</p>
<sample src="examples/UnsafeCodeConstructionSafe.rb" />
</example>
<example>
<p>
As another example, consider the below code which dynamically constructs
a class that has a getter method with a custom name.
</p>
<sample src="examples/UnsafeCodeConstruction2.rb" />
<p>
The example dynamically constructs a string which is then executed using <code>module_eval</code>.
This code will break if the specified name is not a valid Ruby identifier, and
if the value is controlled by an attacker, then this could lead to code-injection.
</p>
<p>
A more robust implementation, that is also immune to code-injection,
can be made by using <code>module_eval</code> with a block and using <code>define_method</code>
to define the getter method.
</p>
<sample src="examples/UnsafeCodeConstruction2Safe.rb" />
</example>
<example>
<p>
This example dynamically registers a method on another class which
forwards its arguments to a target object. This approach uses
<code>module_eval</code> and string interpolation to construct class variables
and methods.
</p>
<sample src="examples/UnsafeCodeConstruction3.rb" />
<p>
A safer approach is to use <code>class_variable_set</code> and
<code>class_variable_get</code> along with <code>define_method</code>. String
interpolation is still used to construct the class variable name, but this is
safe because <code>class_variable_set</code> is not susceptible to code-injection.
</p>
<p>
<code>send</code> is used to dynamically call the method specified by <code>name</code>.
This is a more robust alternative than the previous example, because it does not allow
arbitrary code to be executed, but it does still allow for any method to be called
on the target object.
</p>
<sample src="examples/UnsafeCodeConstruction3Safe.rb" />
</example>
<references>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/Code_Injection">Code Injection</a>.
</li>
<li>
Wikipedia: <a href="https://en.wikipedia.org/wiki/Code_injection">Code Injection</a>.
</li>
<li>
Ruby documentation: <a href="https://docs.ruby-lang.org/en/3.2/Module.html#method-i-define_method">define_method</a>.
</li>
<li>
Ruby documentation: <a href="https://docs.ruby-lang.org/en/3.2/Module.html#method-i-class_variable_set">class_variable_set</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,23 @@
/**
* @name Unsafe code constructed from library input
* @description Using externally controlled strings to construct code may allow a malicious
* user to execute arbitrary code.
* @kind path-problem
* @problem.severity warning
* @security-severity 6.1
* @precision medium
* @id rb/unsafe-code-construction
* @tags security
* external/cwe/cwe-094
* external/cwe/cwe-079
* external/cwe/cwe-116
*/
import codeql.ruby.security.UnsafeCodeConstructionQuery
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where cfg.hasFlowPath(source, sink) and sinkNode = sink.getNode()
select sink.getNode(), source, sink,
"This " + sinkNode.getSinkType() + " which depends on $@ is later $@.", source.getNode(),
"library input", sinkNode.getCodeSink(), "interpreted as code"

View File

@@ -0,0 +1,10 @@
module MyLib
def unsafeDeserialize(value)
eval("foo = #{value}")
foo
end
def unsafeGetter(obj, path)
eval("obj.#{path}")
end
end

View File

@@ -0,0 +1,17 @@
require 'json'
module BadMakeGetter
# Makes a class with a method named `getter_name` that returns `val`
def self.define_getter_class(getter_name, val)
new_class = Class.new
new_class.module_eval <<-END
def #{getter_name}
#{JSON.dump(val)}
end
END
new_class
end
end
one = BadMakeGetter.define_getter_class(:one, "foo")
puts "One is #{one.new.one}"

View File

@@ -0,0 +1,13 @@
# Uses `define_method` instead of constructing a string
module GoodMakeGetter
def self.define_getter_class(getter_name, val)
new_class = Class.new
new_class.module_eval do
define_method(getter_name) { val }
end
new_class
end
end
two = GoodMakeGetter.define_getter_class(:two, "bar")
puts "Two is #{two.new.two}"

View File

@@ -0,0 +1,11 @@
module Invoker
def attach(klass, name, target)
klass.module_eval <<-CODE
@@#{name} = target
def #{name}(*args)
@@#{name}.#{name}(*args)
end
CODE
end
end

View File

@@ -0,0 +1,9 @@
module Invoker
def attach(klass, name, target)
var = :"@@#{name}"
klass.class_variable_set(var, target)
klass.define_method(name) do |*args|
self.class.class_variable_get(var).send(name, *args)
end
end
end

View File

@@ -0,0 +1,11 @@
require 'json'
module MyLib
def safeDeserialize(value)
JSON.parse(value)
end
def safeGetter(obj, path)
obj.dig(*path.split("."))
end
end

View File

@@ -19,6 +19,12 @@
shape, increasing the input length by ten characters may make the
automaton about 1000 times slower.
</p>
<p>
Note that Ruby 3.2 and later have implemented a caching mechanism that
completely eliminates the worst-case time complexity for the regular
expressions flagged by this query. The regular expressions flagged by this
query are therefore only problematic for Ruby versions prior to 3.2.
</p>
<p>
Typically, a regular expression is affected by this problem if it contains
a repetition of the form <code>r*</code> or <code>r+</code> where the

View File

@@ -92,9 +92,9 @@ private predicate maybeCredentialName(string name) {
// Positional parameter
private DataFlow::Node credentialParameter() {
exists(Method m, NamedParameter p, int idx |
exists(Method m, NamedParameter p |
result.asParameter() = p and
p = m.getParameter(idx) and
p = m.getAParameter() and
maybeCredentialName(p.getName())
)
}

View File

@@ -470,293 +470,299 @@ calls/calls.rb:
# 271| getArgument: [SplatExpr] * ...
# 271| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
# 271| getReceiver: [ConstantReadAccess] X
# 274| getStmt: [MethodCall] call to foo
# 274| getReceiver: [SelfVariableAccess] self
# 274| getArgument: [HashSplatExpr] ** ...
# 274| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
# 274| getReceiver: [SelfVariableAccess] self
# 272| getStmt: [MethodCall] call to foo
# 272| getReceiver: [SelfVariableAccess] self
# 272| getArgument: [SplatExpr] * ...
# 275| getStmt: [MethodCall] call to foo
# 275| getReceiver: [SelfVariableAccess] self
# 275| getArgument: [HashSplatExpr] ** ...
# 275| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
# 275| getReceiver: [ConstantReadAccess] X
# 278| getStmt: [MethodCall] call to foo
# 278| getReceiver: [SelfVariableAccess] self
# 278| getArgument: [Pair] Pair
# 278| getKey: [SymbolLiteral] :blah
# 278| getComponent: [StringTextComponent] blah
# 278| getValue: [MethodCall] call to bar
# 278| getReceiver: [SelfVariableAccess] self
# 279| getStmt: [MethodCall] call to foo
# 279| getReceiver: [SelfVariableAccess] self
# 279| getArgument: [Pair] Pair
# 279| getKey: [SymbolLiteral] :blah
# 279| getComponent: [StringTextComponent] blah
# 279| getValue: [MethodCall] call to bar
# 279| getReceiver: [ConstantReadAccess] X
# 284| getStmt: [ClassDeclaration] MyClass
# 285| getStmt: [Method] my_method
# 286| getStmt: [SuperCall] super call to my_method
# 287| getStmt: [SuperCall] super call to my_method
# 275| getReceiver: [SelfVariableAccess] self
# 276| getStmt: [MethodCall] call to foo
# 276| getReceiver: [SelfVariableAccess] self
# 276| getArgument: [HashSplatExpr] ** ...
# 276| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
# 276| getReceiver: [ConstantReadAccess] X
# 277| getStmt: [MethodCall] call to foo
# 277| getReceiver: [SelfVariableAccess] self
# 277| getArgument: [HashSplatExpr] ** ...
# 280| getStmt: [MethodCall] call to foo
# 280| getReceiver: [SelfVariableAccess] self
# 280| getArgument: [Pair] Pair
# 280| getKey: [SymbolLiteral] :blah
# 280| getComponent: [StringTextComponent] blah
# 280| getValue: [MethodCall] call to bar
# 280| getReceiver: [SelfVariableAccess] self
# 281| getStmt: [MethodCall] call to foo
# 281| getReceiver: [SelfVariableAccess] self
# 281| getArgument: [Pair] Pair
# 281| getKey: [SymbolLiteral] :blah
# 281| getComponent: [StringTextComponent] blah
# 281| getValue: [MethodCall] call to bar
# 281| getReceiver: [ConstantReadAccess] X
# 286| getStmt: [ClassDeclaration] MyClass
# 287| getStmt: [Method] my_method
# 288| getStmt: [SuperCall] super call to my_method
# 288| getArgument: [StringLiteral] "blah"
# 288| getComponent: [StringTextComponent] blah
# 289| getStmt: [SuperCall] super call to my_method
# 289| getArgument: [IntegerLiteral] 1
# 289| getArgument: [IntegerLiteral] 2
# 289| getArgument: [IntegerLiteral] 3
# 290| getStmt: [SuperCall] super call to my_method
# 290| getBlock: [BraceBlock] { ... }
# 290| getParameter: [SimpleParameter] x
# 290| getDefiningAccess: [LocalVariableAccess] x
# 290| getStmt: [AddExpr] ... + ...
# 290| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
# 290| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 290| getArgument: [StringLiteral] "blah"
# 290| getComponent: [StringTextComponent] blah
# 291| getStmt: [SuperCall] super call to my_method
# 291| getBlock: [DoBlock] do ... end
# 291| getParameter: [SimpleParameter] x
# 291| getDefiningAccess: [LocalVariableAccess] x
# 291| getStmt: [MulExpr] ... * ...
# 291| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
# 291| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
# 291| getArgument: [IntegerLiteral] 1
# 291| getArgument: [IntegerLiteral] 2
# 291| getArgument: [IntegerLiteral] 3
# 292| getStmt: [SuperCall] super call to my_method
# 292| getArgument: [IntegerLiteral] 4
# 292| getArgument: [IntegerLiteral] 5
# 292| getBlock: [BraceBlock] { ... }
# 292| getParameter: [SimpleParameter] x
# 292| getDefiningAccess: [LocalVariableAccess] x
# 292| getStmt: [AddExpr] ... + ...
# 292| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
# 292| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 100
# 292| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 293| getStmt: [SuperCall] super call to my_method
# 293| getArgument: [IntegerLiteral] 6
# 293| getArgument: [IntegerLiteral] 7
# 293| getBlock: [DoBlock] do ... end
# 293| getParameter: [SimpleParameter] x
# 293| getDefiningAccess: [LocalVariableAccess] x
# 293| getStmt: [AddExpr] ... + ...
# 293| getStmt: [MulExpr] ... * ...
# 293| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
# 293| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 200
# 301| getStmt: [ClassDeclaration] AnotherClass
# 302| getStmt: [Method] another_method
# 303| getStmt: [MethodCall] call to super
# 303| getReceiver: [MethodCall] call to foo
# 303| getReceiver: [SelfVariableAccess] self
# 304| getStmt: [MethodCall] call to super
# 304| getReceiver: [SelfVariableAccess] self
# 293| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
# 294| getStmt: [SuperCall] super call to my_method
# 294| getArgument: [IntegerLiteral] 4
# 294| getArgument: [IntegerLiteral] 5
# 294| getBlock: [BraceBlock] { ... }
# 294| getParameter: [SimpleParameter] x
# 294| getDefiningAccess: [LocalVariableAccess] x
# 294| getStmt: [AddExpr] ... + ...
# 294| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
# 294| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 100
# 295| getStmt: [SuperCall] super call to my_method
# 295| getArgument: [IntegerLiteral] 6
# 295| getArgument: [IntegerLiteral] 7
# 295| getBlock: [DoBlock] do ... end
# 295| getParameter: [SimpleParameter] x
# 295| getDefiningAccess: [LocalVariableAccess] x
# 295| getStmt: [AddExpr] ... + ...
# 295| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
# 295| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 200
# 303| getStmt: [ClassDeclaration] AnotherClass
# 304| getStmt: [Method] another_method
# 305| getStmt: [MethodCall] call to super
# 305| getReceiver: [SuperCall] super call to another_method
# 310| getStmt: [MethodCall] call to call
# 310| getReceiver: [MethodCall] call to foo
# 310| getReceiver: [SelfVariableAccess] self
# 311| getStmt: [MethodCall] call to call
# 311| getReceiver: [MethodCall] call to foo
# 311| getReceiver: [SelfVariableAccess] self
# 311| getArgument: [IntegerLiteral] 1
# 314| getStmt: [AssignExpr] ... = ...
# 314| getAnOperand/getLeftOperand: [MethodCall] call to foo
# 314| getReceiver: [SelfVariableAccess] self
# 314| getAnOperand/getRightOperand: [IntegerLiteral] 10
# 315| getStmt: [AssignExpr] ... = ...
# 315| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 315| getReceiver: [MethodCall] call to foo
# 315| getReceiver: [SelfVariableAccess] self
# 315| getArgument: [IntegerLiteral] 0
# 315| getAnOperand/getRightOperand: [IntegerLiteral] 10
# 305| getReceiver: [MethodCall] call to foo
# 305| getReceiver: [SelfVariableAccess] self
# 306| getStmt: [MethodCall] call to super
# 306| getReceiver: [SelfVariableAccess] self
# 307| getStmt: [MethodCall] call to super
# 307| getReceiver: [SuperCall] super call to another_method
# 312| getStmt: [MethodCall] call to call
# 312| getReceiver: [MethodCall] call to foo
# 312| getReceiver: [SelfVariableAccess] self
# 313| getStmt: [MethodCall] call to call
# 313| getReceiver: [MethodCall] call to foo
# 313| getReceiver: [SelfVariableAccess] self
# 313| getArgument: [IntegerLiteral] 1
# 316| getStmt: [AssignExpr] ... = ...
# 316| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...)
# 316| getElement: [MethodCall] call to foo
# 316| getReceiver: [SelfVariableAccess] self
# 316| getElement: [MethodCall] call to bar
# 316| getReceiver: [SelfVariableAccess] self
# 316| getElement: [ElementReference] ...[...]
# 316| getReceiver: [MethodCall] call to foo
# 316| getReceiver: [SelfVariableAccess] self
# 316| getArgument: [IntegerLiteral] 4
# 316| getAnOperand/getRightOperand: [ArrayLiteral] [...]
# 316| getElement: [IntegerLiteral] 1
# 316| getElement: [IntegerLiteral] 2
# 316| getElement: [IntegerLiteral] 3
# 316| getElement: [IntegerLiteral] 4
# 316| getAnOperand/getLeftOperand: [MethodCall] call to foo
# 316| getReceiver: [SelfVariableAccess] self
# 316| getAnOperand/getRightOperand: [IntegerLiteral] 10
# 317| getStmt: [AssignExpr] ... = ...
# 317| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...)
# 317| getElement: [LocalVariableAccess] a
# 317| getElement: [ElementReference] ...[...]
# 317| getReceiver: [MethodCall] call to foo
# 317| getReceiver: [SelfVariableAccess] self
# 317| getArgument: [IntegerLiteral] 5
# 317| getAnOperand/getRightOperand: [ArrayLiteral] [...]
# 317| getElement: [IntegerLiteral] 1
# 317| getElement: [IntegerLiteral] 2
# 317| getElement: [IntegerLiteral] 3
# 318| getStmt: [AssignAddExpr] ... += ...
# 318| getAnOperand/getLeftOperand: [MethodCall] call to count
# 318| getReceiver: [SelfVariableAccess] self
# 318| getAnOperand/getRightOperand: [IntegerLiteral] 1
# 319| getStmt: [AssignAddExpr] ... += ...
# 319| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 319| getReceiver: [MethodCall] call to foo
# 319| getReceiver: [SelfVariableAccess] self
# 319| getArgument: [IntegerLiteral] 0
# 319| getAnOperand/getRightOperand: [IntegerLiteral] 1
# 320| getStmt: [AssignMulExpr] ... *= ...
# 320| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 320| getReceiver: [MethodCall] call to bar
# 320| getReceiver: [MethodCall] call to foo
# 320| getReceiver: [SelfVariableAccess] self
# 320| getArgument: [IntegerLiteral] 0
# 320| getArgument: [MethodCall] call to baz
# 320| getReceiver: [MethodCall] call to foo
# 320| getReceiver: [SelfVariableAccess] self
# 320| getArgument: [AddExpr] ... + ...
# 320| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to boo
# 320| getReceiver: [MethodCall] call to foo
# 320| getReceiver: [SelfVariableAccess] self
# 320| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 320| getAnOperand/getRightOperand: [IntegerLiteral] 2
# 323| getStmt: [Method] foo
# 323| getStmt: [MethodCall] call to bar
# 323| getReceiver: [SelfVariableAccess] self
# 324| getStmt: [Method] foo
# 324| getStmt: [MethodCall] call to bar
# 324| getReceiver: [SelfVariableAccess] self
# 317| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 317| getReceiver: [MethodCall] call to foo
# 317| getReceiver: [SelfVariableAccess] self
# 317| getArgument: [IntegerLiteral] 0
# 317| getAnOperand/getRightOperand: [IntegerLiteral] 10
# 318| getStmt: [AssignExpr] ... = ...
# 318| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...)
# 318| getElement: [MethodCall] call to foo
# 318| getReceiver: [SelfVariableAccess] self
# 318| getElement: [MethodCall] call to bar
# 318| getReceiver: [SelfVariableAccess] self
# 318| getElement: [ElementReference] ...[...]
# 318| getReceiver: [MethodCall] call to foo
# 318| getReceiver: [SelfVariableAccess] self
# 318| getArgument: [IntegerLiteral] 4
# 318| getAnOperand/getRightOperand: [ArrayLiteral] [...]
# 318| getElement: [IntegerLiteral] 1
# 318| getElement: [IntegerLiteral] 2
# 318| getElement: [IntegerLiteral] 3
# 318| getElement: [IntegerLiteral] 4
# 319| getStmt: [AssignExpr] ... = ...
# 319| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...)
# 319| getElement: [LocalVariableAccess] a
# 319| getElement: [ElementReference] ...[...]
# 319| getReceiver: [MethodCall] call to foo
# 319| getReceiver: [SelfVariableAccess] self
# 319| getArgument: [IntegerLiteral] 5
# 319| getAnOperand/getRightOperand: [ArrayLiteral] [...]
# 319| getElement: [IntegerLiteral] 1
# 319| getElement: [IntegerLiteral] 2
# 319| getElement: [IntegerLiteral] 3
# 320| getStmt: [AssignAddExpr] ... += ...
# 320| getAnOperand/getLeftOperand: [MethodCall] call to count
# 320| getReceiver: [SelfVariableAccess] self
# 320| getAnOperand/getRightOperand: [IntegerLiteral] 1
# 321| getStmt: [AssignAddExpr] ... += ...
# 321| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 321| getReceiver: [MethodCall] call to foo
# 321| getReceiver: [SelfVariableAccess] self
# 321| getArgument: [IntegerLiteral] 0
# 321| getAnOperand/getRightOperand: [IntegerLiteral] 1
# 322| getStmt: [AssignMulExpr] ... *= ...
# 322| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 322| getReceiver: [MethodCall] call to bar
# 322| getReceiver: [MethodCall] call to foo
# 322| getReceiver: [SelfVariableAccess] self
# 322| getArgument: [IntegerLiteral] 0
# 322| getArgument: [MethodCall] call to baz
# 322| getReceiver: [MethodCall] call to foo
# 322| getReceiver: [SelfVariableAccess] self
# 322| getArgument: [AddExpr] ... + ...
# 322| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to boo
# 322| getReceiver: [MethodCall] call to foo
# 322| getReceiver: [SelfVariableAccess] self
# 322| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 322| getAnOperand/getRightOperand: [IntegerLiteral] 2
# 325| getStmt: [Method] foo
# 325| getParameter: [SimpleParameter] x
# 325| getDefiningAccess: [LocalVariableAccess] x
# 325| getStmt: [MethodCall] call to bar
# 325| getReceiver: [SelfVariableAccess] self
# 326| getStmt: [SingletonMethod] foo
# 326| getObject: [ConstantReadAccess] Object
# 326| getStmt: [Method] foo
# 326| getStmt: [MethodCall] call to bar
# 326| getReceiver: [SelfVariableAccess] self
# 327| getStmt: [SingletonMethod] foo
# 327| getObject: [ConstantReadAccess] Object
# 327| getStmt: [Method] foo
# 327| getParameter: [SimpleParameter] x
# 327| getDefiningAccess: [LocalVariableAccess] x
# 327| getStmt: [MethodCall] call to bar
# 327| getReceiver: [SelfVariableAccess] self
# 328| getStmt: [Method] foo
# 328| getStmt: [RescueModifierExpr] ... rescue ...
# 328| getBody: [MethodCall] call to bar
# 328| getReceiver: [SelfVariableAccess] self
# 328| getHandler: [ParenthesizedExpr] ( ... )
# 328| getStmt: [MethodCall] call to print
# 328| getReceiver: [SelfVariableAccess] self
# 328| getArgument: [StringLiteral] "error"
# 328| getComponent: [StringTextComponent] error
# 331| getStmt: [Method] foo
# 331| getParameter: [ForwardParameter] ...
# 332| getStmt: [SuperCall] super call to foo
# 332| getArgument: [ForwardedArguments] ...
# 335| getStmt: [Method] foo
# 335| getParameter: [SimpleParameter] a
# 335| getDefiningAccess: [LocalVariableAccess] a
# 335| getParameter: [SimpleParameter] b
# 335| getDefiningAccess: [LocalVariableAccess] b
# 335| getParameter: [ForwardParameter] ...
# 336| getStmt: [MethodCall] call to bar
# 336| getReceiver: [SelfVariableAccess] self
# 336| getArgument: [LocalVariableAccess] b
# 336| getArgument: [ForwardedArguments] ...
# 340| getStmt: [ForExpr] for ... in ...
# 340| getPattern: [DestructuredLhsExpr] (..., ...)
# 340| getElement: [LocalVariableAccess] x
# 340| getElement: [LocalVariableAccess] y
# 340| getElement: [LocalVariableAccess] z
# 340| getValue: [ArrayLiteral] [...]
# 340| getElement: [ArrayLiteral] [...]
# 340| getElement: [IntegerLiteral] 1
# 340| getElement: [IntegerLiteral] 2
# 340| getElement: [IntegerLiteral] 3
# 340| getElement: [ArrayLiteral] [...]
# 340| getElement: [IntegerLiteral] 4
# 340| getElement: [IntegerLiteral] 5
# 340| getElement: [IntegerLiteral] 6
# 340| getBody: [StmtSequence] do ...
# 341| getStmt: [MethodCall] call to foo
# 341| getReceiver: [SelfVariableAccess] self
# 341| getArgument: [LocalVariableAccess] x
# 341| getArgument: [LocalVariableAccess] y
# 341| getArgument: [LocalVariableAccess] z
# 344| getStmt: [MethodCall] call to foo
# 344| getReceiver: [SelfVariableAccess] self
# 344| getArgument: [Pair] Pair
# 344| getKey: [SymbolLiteral] :x
# 344| getComponent: [StringTextComponent] x
# 344| getValue: [IntegerLiteral] 42
# 345| getStmt: [MethodCall] call to foo
# 345| getReceiver: [SelfVariableAccess] self
# 345| getArgument: [Pair] Pair
# 345| getKey: [SymbolLiteral] :x
# 345| getComponent: [StringTextComponent] x
# 345| getValue: [LocalVariableAccess] x
# 345| getArgument: [Pair] Pair
# 345| getKey: [SymbolLiteral] :novar
# 345| getComponent: [StringTextComponent] novar
# 345| getValue: [MethodCall] call to novar
# 328| getStmt: [SingletonMethod] foo
# 328| getObject: [ConstantReadAccess] Object
# 328| getStmt: [MethodCall] call to bar
# 328| getReceiver: [SelfVariableAccess] self
# 329| getStmt: [SingletonMethod] foo
# 329| getObject: [ConstantReadAccess] Object
# 329| getParameter: [SimpleParameter] x
# 329| getDefiningAccess: [LocalVariableAccess] x
# 329| getStmt: [MethodCall] call to bar
# 329| getReceiver: [SelfVariableAccess] self
# 330| getStmt: [Method] foo
# 330| getStmt: [RescueModifierExpr] ... rescue ...
# 330| getBody: [MethodCall] call to bar
# 330| getReceiver: [SelfVariableAccess] self
# 330| getHandler: [ParenthesizedExpr] ( ... )
# 330| getStmt: [MethodCall] call to print
# 330| getReceiver: [SelfVariableAccess] self
# 330| getArgument: [StringLiteral] "error"
# 330| getComponent: [StringTextComponent] error
# 333| getStmt: [Method] foo
# 333| getParameter: [ForwardParameter] ...
# 334| getStmt: [SuperCall] super call to foo
# 334| getArgument: [ForwardedArguments] ...
# 337| getStmt: [Method] foo
# 337| getParameter: [SimpleParameter] a
# 337| getDefiningAccess: [LocalVariableAccess] a
# 337| getParameter: [SimpleParameter] b
# 337| getDefiningAccess: [LocalVariableAccess] b
# 337| getParameter: [ForwardParameter] ...
# 338| getStmt: [MethodCall] call to bar
# 338| getReceiver: [SelfVariableAccess] self
# 338| getArgument: [LocalVariableAccess] b
# 338| getArgument: [ForwardedArguments] ...
# 342| getStmt: [ForExpr] for ... in ...
# 342| getPattern: [DestructuredLhsExpr] (..., ...)
# 342| getElement: [LocalVariableAccess] x
# 342| getElement: [LocalVariableAccess] y
# 342| getElement: [LocalVariableAccess] z
# 342| getValue: [ArrayLiteral] [...]
# 342| getElement: [ArrayLiteral] [...]
# 342| getElement: [IntegerLiteral] 1
# 342| getElement: [IntegerLiteral] 2
# 342| getElement: [IntegerLiteral] 3
# 342| getElement: [ArrayLiteral] [...]
# 342| getElement: [IntegerLiteral] 4
# 342| getElement: [IntegerLiteral] 5
# 342| getElement: [IntegerLiteral] 6
# 342| getBody: [StmtSequence] do ...
# 343| getStmt: [MethodCall] call to foo
# 343| getReceiver: [SelfVariableAccess] self
# 343| getArgument: [LocalVariableAccess] x
# 343| getArgument: [LocalVariableAccess] y
# 343| getArgument: [LocalVariableAccess] z
# 346| getStmt: [MethodCall] call to foo
# 346| getReceiver: [SelfVariableAccess] self
# 346| getArgument: [Pair] Pair
# 346| getKey: [SymbolLiteral] :X
# 346| getComponent: [StringTextComponent] X
# 346| getKey: [SymbolLiteral] :x
# 346| getComponent: [StringTextComponent] x
# 346| getValue: [IntegerLiteral] 42
# 347| getStmt: [MethodCall] call to foo
# 347| getReceiver: [SelfVariableAccess] self
# 347| getArgument: [Pair] Pair
# 347| getKey: [SymbolLiteral] :X
# 347| getComponent: [StringTextComponent] X
# 347| getValue: [ConstantReadAccess] X
# 350| getStmt: [AssignExpr] ... = ...
# 350| getAnOperand/getLeftOperand: [LocalVariableAccess] y
# 350| getAnOperand/getRightOperand: [IntegerLiteral] 1
# 351| getStmt: [AssignExpr] ... = ...
# 351| getAnOperand/getLeftOperand: [LocalVariableAccess] one
# 351| getAnOperand/getRightOperand: [Lambda] -> { ... }
# 351| getParameter: [SimpleParameter] x
# 351| getDefiningAccess: [LocalVariableAccess] x
# 351| getStmt: [LocalVariableAccess] y
# 347| getKey: [SymbolLiteral] :x
# 347| getComponent: [StringTextComponent] x
# 347| getValue: [LocalVariableAccess] x
# 347| getArgument: [Pair] Pair
# 347| getKey: [SymbolLiteral] :novar
# 347| getComponent: [StringTextComponent] novar
# 347| getValue: [MethodCall] call to novar
# 348| getStmt: [MethodCall] call to foo
# 348| getReceiver: [SelfVariableAccess] self
# 348| getArgument: [Pair] Pair
# 348| getKey: [SymbolLiteral] :X
# 348| getComponent: [StringTextComponent] X
# 348| getValue: [IntegerLiteral] 42
# 349| getStmt: [MethodCall] call to foo
# 349| getReceiver: [SelfVariableAccess] self
# 349| getArgument: [Pair] Pair
# 349| getKey: [SymbolLiteral] :X
# 349| getComponent: [StringTextComponent] X
# 349| getValue: [ConstantReadAccess] X
# 352| getStmt: [AssignExpr] ... = ...
# 352| getAnOperand/getLeftOperand: [LocalVariableAccess] f
# 352| getAnOperand/getRightOperand: [Lambda] -> { ... }
# 352| getParameter: [SimpleParameter] x
# 352| getDefiningAccess: [LocalVariableAccess] x
# 352| getStmt: [MethodCall] call to foo
# 352| getReceiver: [SelfVariableAccess] self
# 352| getArgument: [LocalVariableAccess] x
# 352| getAnOperand/getLeftOperand: [LocalVariableAccess] y
# 352| getAnOperand/getRightOperand: [IntegerLiteral] 1
# 353| getStmt: [AssignExpr] ... = ...
# 353| getAnOperand/getLeftOperand: [LocalVariableAccess] g
# 353| getAnOperand/getLeftOperand: [LocalVariableAccess] one
# 353| getAnOperand/getRightOperand: [Lambda] -> { ... }
# 353| getParameter: [SimpleParameter] x
# 353| getDefiningAccess: [LocalVariableAccess] x
# 353| getStmt: [MethodCall] call to unknown_call
# 353| getReceiver: [SelfVariableAccess] self
# 353| getStmt: [LocalVariableAccess] y
# 354| getStmt: [AssignExpr] ... = ...
# 354| getAnOperand/getLeftOperand: [LocalVariableAccess] h
# 354| getAnOperand/getLeftOperand: [LocalVariableAccess] f
# 354| getAnOperand/getRightOperand: [Lambda] -> { ... }
# 354| getParameter: [SimpleParameter] x
# 354| getDefiningAccess: [LocalVariableAccess] x
# 355| getStmt: [LocalVariableAccess] x
# 356| getStmt: [LocalVariableAccess] y
# 357| getStmt: [MethodCall] call to unknown_call
# 357| getReceiver: [SelfVariableAccess] self
# 361| getStmt: [MethodCall] call to empty?
# 361| getReceiver: [MethodCall] call to list
# 361| getReceiver: [SelfVariableAccess] self
# 362| getStmt: [MethodCall] call to empty?
# 362| getReceiver: [MethodCall] call to list
# 362| getReceiver: [SelfVariableAccess] self
# 354| getStmt: [MethodCall] call to foo
# 354| getReceiver: [SelfVariableAccess] self
# 354| getArgument: [LocalVariableAccess] x
# 355| getStmt: [AssignExpr] ... = ...
# 355| getAnOperand/getLeftOperand: [LocalVariableAccess] g
# 355| getAnOperand/getRightOperand: [Lambda] -> { ... }
# 355| getParameter: [SimpleParameter] x
# 355| getDefiningAccess: [LocalVariableAccess] x
# 355| getStmt: [MethodCall] call to unknown_call
# 355| getReceiver: [SelfVariableAccess] self
# 356| getStmt: [AssignExpr] ... = ...
# 356| getAnOperand/getLeftOperand: [LocalVariableAccess] h
# 356| getAnOperand/getRightOperand: [Lambda] -> { ... }
# 356| getParameter: [SimpleParameter] x
# 356| getDefiningAccess: [LocalVariableAccess] x
# 357| getStmt: [LocalVariableAccess] x
# 358| getStmt: [LocalVariableAccess] y
# 359| getStmt: [MethodCall] call to unknown_call
# 359| getReceiver: [SelfVariableAccess] self
# 363| getStmt: [MethodCall] call to empty?
# 363| getReceiver: [MethodCall] call to list
# 363| getReceiver: [SelfVariableAccess] self
# 364| getStmt: [MethodCall] call to bar
# 364| getReceiver: [MethodCall] call to foo
# 364| getStmt: [MethodCall] call to empty?
# 364| getReceiver: [MethodCall] call to list
# 364| getReceiver: [SelfVariableAccess] self
# 364| getArgument: [IntegerLiteral] 1
# 364| getArgument: [IntegerLiteral] 2
# 364| getBlock: [BraceBlock] { ... }
# 364| getParameter: [SimpleParameter] x
# 364| getDefiningAccess: [LocalVariableAccess] x
# 364| getStmt: [LocalVariableAccess] x
# 365| getStmt: [MethodCall] call to empty?
# 365| getReceiver: [MethodCall] call to list
# 365| getReceiver: [SelfVariableAccess] self
# 366| getStmt: [MethodCall] call to bar
# 366| getReceiver: [MethodCall] call to foo
# 366| getReceiver: [SelfVariableAccess] self
# 366| getArgument: [IntegerLiteral] 1
# 366| getArgument: [IntegerLiteral] 2
# 366| getBlock: [BraceBlock] { ... }
# 366| getParameter: [SimpleParameter] x
# 366| getDefiningAccess: [LocalVariableAccess] x
# 366| getStmt: [LocalVariableAccess] x
control/cases.rb:
# 1| [Toplevel] cases.rb
# 2| getStmt: [AssignExpr] ... = ...
@@ -3089,6 +3095,24 @@ params/params.rb:
# 86| getStmt: [MethodCall] call to puts
# 86| getReceiver: [SelfVariableAccess] self
# 86| getArgument: [LocalVariableAccess] x
# 89| getStmt: [Method] anonymous_splat_parameter
# 89| getParameter: [SimpleParameter] array
# 89| getDefiningAccess: [LocalVariableAccess] array
# 89| getParameter: [SplatParameter] *
# 89| getDefiningAccess: [LocalVariableAccess] __synth__0
# 90| getStmt: [MethodCall] call to concat
# 90| getReceiver: [LocalVariableAccess] array
# 90| getArgument: [SplatExpr] * ...
# 90| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] __synth__0
# 94| getStmt: [Method] anonymous_hash_splat_parameter
# 94| getParameter: [SimpleParameter] hash
# 94| getDefiningAccess: [LocalVariableAccess] hash
# 94| getParameter: [HashSplatParameter] **
# 94| getDefiningAccess: [LocalVariableAccess] __synth__0
# 95| getStmt: [MethodCall] call to merge
# 95| getReceiver: [LocalVariableAccess] hash
# 95| getArgument: [HashSplatExpr] ** ...
# 95| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] __synth__0
erb/template.html.erb:
# 19| [Toplevel] template.html.erb
# 19| getStmt: [StringLiteral] "hello world"

View File

@@ -60,257 +60,257 @@ calls/calls.rb:
# 249| getReceiver: [ConstantReadAccess] X
# 249| getValue: [MethodCall] call to bar
# 249| getReceiver: [ConstantReadAccess] X
# 314| [AssignExpr] ... = ...
# 314| getDesugared: [StmtSequence] ...
# 314| getStmt: [SetterMethodCall] call to foo=
# 314| getReceiver: [SelfVariableAccess] self
# 314| getArgument: [AssignExpr] ... = ...
# 314| getAnOperand/getRightOperand: [IntegerLiteral] 10
# 314| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 314| getStmt: [LocalVariableAccess] __synth__0
# 315| [AssignExpr] ... = ...
# 315| getDesugared: [StmtSequence] ...
# 315| getStmt: [SetterMethodCall] call to []=
# 315| getReceiver: [MethodCall] call to foo
# 315| getReceiver: [SelfVariableAccess] self
# 315| getArgument: [IntegerLiteral] 0
# 315| getArgument: [AssignExpr] ... = ...
# 315| getAnOperand/getRightOperand: [IntegerLiteral] 10
# 315| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 315| getStmt: [LocalVariableAccess] __synth__0
# 316| [AssignExpr] ... = ...
# 316| getDesugared: [StmtSequence] ...
# 316| getStmt: [AssignExpr] ... = ...
# 316| getAnOperand/getLeftOperand: [MethodCall] call to foo
# 316| getDesugared: [StmtSequence] ...
# 316| getStmt: [SetterMethodCall] call to foo=
# 316| getReceiver: [SelfVariableAccess] self
# 316| getArgument: [AssignExpr] ... = ...
# 316| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 316| getAnOperand/getRightOperand: [MethodCall] call to []
# 316| getReceiver: [LocalVariableAccess] __synth__0
# 316| getArgument: [IntegerLiteral] 0
# 316| getStmt: [LocalVariableAccess] __synth__0__1
# 316| getStmt: [AssignExpr] ... = ...
# 316| getAnOperand/getLeftOperand: [MethodCall] call to bar
# 316| getDesugared: [StmtSequence] ...
# 316| getStmt: [SetterMethodCall] call to bar=
# 316| getReceiver: [SelfVariableAccess] self
# 316| getArgument: [AssignExpr] ... = ...
# 316| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 316| getAnOperand/getRightOperand: [MethodCall] call to []
# 316| getReceiver: [LocalVariableAccess] __synth__0
# 316| getArgument: [RangeLiteral] _ .. _
# 316| getBegin: [IntegerLiteral] 1
# 316| getEnd: [IntegerLiteral] -2
# 316| getStmt: [LocalVariableAccess] __synth__0__1
# 316| getStmt: [AssignExpr] ... = ...
# 316| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 316| getDesugared: [StmtSequence] ...
# 316| getStmt: [SetterMethodCall] call to []=
# 316| getReceiver: [MethodCall] call to foo
# 316| getReceiver: [SelfVariableAccess] self
# 316| getArgument: [AssignExpr] ... = ...
# 316| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 316| getAnOperand/getRightOperand: [MethodCall] call to []
# 316| getReceiver: [LocalVariableAccess] __synth__0
# 316| getArgument: [IntegerLiteral] -1
# 316| getArgument: [IntegerLiteral] 4
# 316| getStmt: [LocalVariableAccess] __synth__0__1
# 316| getStmt: [AssignExpr] ... = ...
# 316| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 316| getAnOperand/getRightOperand: [SplatExpr] * ...
# 316| getAnOperand/getOperand/getReceiver: [ArrayLiteral] [...]
# 316| getDesugared: [MethodCall] call to []
# 316| getReceiver: [ConstantReadAccess] Array
# 316| getArgument: [IntegerLiteral] 1
# 316| getArgument: [IntegerLiteral] 2
# 316| getArgument: [IntegerLiteral] 3
# 316| getArgument: [IntegerLiteral] 4
# 316| getStmt: [SetterMethodCall] call to foo=
# 316| getReceiver: [SelfVariableAccess] self
# 316| getArgument: [AssignExpr] ... = ...
# 316| getAnOperand/getRightOperand: [IntegerLiteral] 10
# 316| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 316| getStmt: [LocalVariableAccess] __synth__0
# 317| [AssignExpr] ... = ...
# 317| getDesugared: [StmtSequence] ...
# 317| getStmt: [AssignExpr] ... = ...
# 317| getAnOperand/getLeftOperand: [LocalVariableAccess] a
# 317| getAnOperand/getRightOperand: [MethodCall] call to []
# 317| getReceiver: [LocalVariableAccess] __synth__0
# 317| getArgument: [IntegerLiteral] 0
# 317| getStmt: [AssignExpr] ... = ...
# 317| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 317| getDesugared: [StmtSequence] ...
# 317| getStmt: [SetterMethodCall] call to []=
# 317| getReceiver: [MethodCall] call to foo
# 317| getReceiver: [SelfVariableAccess] self
# 317| getArgument: [AssignExpr] ... = ...
# 317| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 317| getAnOperand/getRightOperand: [MethodCall] call to []
# 317| getReceiver: [LocalVariableAccess] __synth__0
# 317| getArgument: [RangeLiteral] _ .. _
# 317| getBegin: [IntegerLiteral] 1
# 317| getEnd: [IntegerLiteral] -1
# 317| getArgument: [IntegerLiteral] 5
# 317| getStmt: [LocalVariableAccess] __synth__0__1
# 317| getStmt: [AssignExpr] ... = ...
# 317| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 317| getAnOperand/getRightOperand: [SplatExpr] * ...
# 317| getAnOperand/getOperand/getReceiver: [ArrayLiteral] [...]
# 317| getDesugared: [MethodCall] call to []
# 317| getReceiver: [ConstantReadAccess] Array
# 317| getArgument: [IntegerLiteral] 1
# 317| getArgument: [IntegerLiteral] 2
# 317| getArgument: [IntegerLiteral] 3
# 318| [AssignAddExpr] ... += ...
# 317| getStmt: [SetterMethodCall] call to []=
# 317| getReceiver: [MethodCall] call to foo
# 317| getReceiver: [SelfVariableAccess] self
# 317| getArgument: [IntegerLiteral] 0
# 317| getArgument: [AssignExpr] ... = ...
# 317| getAnOperand/getRightOperand: [IntegerLiteral] 10
# 317| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 317| getStmt: [LocalVariableAccess] __synth__0
# 318| [AssignExpr] ... = ...
# 318| getDesugared: [StmtSequence] ...
# 318| getStmt: [AssignExpr] ... = ...
# 318| getAnOperand/getRightOperand: [SelfVariableAccess] self
# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 318| getStmt: [SetterMethodCall] call to count=
# 318| getReceiver: [LocalVariableAccess] __synth__0
# 318| getArgument: [LocalVariableAccess] __synth__1
# 318| getAnOperand/getLeftOperand: [MethodCall] call to foo
# 318| getDesugared: [StmtSequence] ...
# 318| getStmt: [SetterMethodCall] call to foo=
# 318| getReceiver: [SelfVariableAccess] self
# 318| getArgument: [AssignExpr] ... = ...
# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 318| getAnOperand/getRightOperand: [MethodCall] call to []
# 318| getReceiver: [LocalVariableAccess] __synth__0
# 318| getArgument: [IntegerLiteral] 0
# 318| getStmt: [LocalVariableAccess] __synth__0__1
# 318| getStmt: [AssignExpr] ... = ...
# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1
# 318| getAnOperand/getRightOperand: [AddExpr] ... + ...
# 318| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to count
# 318| getReceiver: [LocalVariableAccess] __synth__0
# 318| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 318| getStmt: [LocalVariableAccess] __synth__1
# 319| [AssignAddExpr] ... += ...
# 318| getAnOperand/getLeftOperand: [MethodCall] call to bar
# 318| getDesugared: [StmtSequence] ...
# 318| getStmt: [SetterMethodCall] call to bar=
# 318| getReceiver: [SelfVariableAccess] self
# 318| getArgument: [AssignExpr] ... = ...
# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 318| getAnOperand/getRightOperand: [MethodCall] call to []
# 318| getReceiver: [LocalVariableAccess] __synth__0
# 318| getArgument: [RangeLiteral] _ .. _
# 318| getBegin: [IntegerLiteral] 1
# 318| getEnd: [IntegerLiteral] -2
# 318| getStmt: [LocalVariableAccess] __synth__0__1
# 318| getStmt: [AssignExpr] ... = ...
# 318| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 318| getDesugared: [StmtSequence] ...
# 318| getStmt: [SetterMethodCall] call to []=
# 318| getReceiver: [MethodCall] call to foo
# 318| getReceiver: [SelfVariableAccess] self
# 318| getArgument: [AssignExpr] ... = ...
# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 318| getAnOperand/getRightOperand: [MethodCall] call to []
# 318| getReceiver: [LocalVariableAccess] __synth__0
# 318| getArgument: [IntegerLiteral] -1
# 318| getArgument: [IntegerLiteral] 4
# 318| getStmt: [LocalVariableAccess] __synth__0__1
# 318| getStmt: [AssignExpr] ... = ...
# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 318| getAnOperand/getRightOperand: [SplatExpr] * ...
# 318| getAnOperand/getOperand/getReceiver: [ArrayLiteral] [...]
# 318| getDesugared: [MethodCall] call to []
# 318| getReceiver: [ConstantReadAccess] Array
# 318| getArgument: [IntegerLiteral] 1
# 318| getArgument: [IntegerLiteral] 2
# 318| getArgument: [IntegerLiteral] 3
# 318| getArgument: [IntegerLiteral] 4
# 319| [AssignExpr] ... = ...
# 319| getDesugared: [StmtSequence] ...
# 319| getStmt: [AssignExpr] ... = ...
# 319| getAnOperand/getRightOperand: [MethodCall] call to foo
# 319| getReceiver: [SelfVariableAccess] self
# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] a
# 319| getAnOperand/getRightOperand: [MethodCall] call to []
# 319| getReceiver: [LocalVariableAccess] __synth__0
# 319| getArgument: [IntegerLiteral] 0
# 319| getStmt: [AssignExpr] ... = ...
# 319| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 319| getDesugared: [StmtSequence] ...
# 319| getStmt: [SetterMethodCall] call to []=
# 319| getReceiver: [MethodCall] call to foo
# 319| getReceiver: [SelfVariableAccess] self
# 319| getArgument: [AssignExpr] ... = ...
# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 319| getAnOperand/getRightOperand: [MethodCall] call to []
# 319| getReceiver: [LocalVariableAccess] __synth__0
# 319| getArgument: [RangeLiteral] _ .. _
# 319| getBegin: [IntegerLiteral] 1
# 319| getEnd: [IntegerLiteral] -1
# 319| getArgument: [IntegerLiteral] 5
# 319| getStmt: [LocalVariableAccess] __synth__0__1
# 319| getStmt: [AssignExpr] ... = ...
# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 319| getStmt: [SetterMethodCall] call to []=
# 319| getReceiver: [LocalVariableAccess] __synth__0
# 319| getArgument: [LocalVariableAccess] __synth__1
# 319| getArgument: [LocalVariableAccess] __synth__2
# 319| getStmt: [AssignExpr] ... = ...
# 319| getAnOperand/getRightOperand: [IntegerLiteral] 0
# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1
# 319| getStmt: [AssignExpr] ... = ...
# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2
# 319| getAnOperand/getRightOperand: [AddExpr] ... + ...
# 319| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to []
# 319| getReceiver: [LocalVariableAccess] __synth__0
# 319| getArgument: [LocalVariableAccess] __synth__1
# 319| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 319| getStmt: [LocalVariableAccess] __synth__2
# 320| [AssignMulExpr] ... *= ...
# 319| getAnOperand/getRightOperand: [SplatExpr] * ...
# 319| getAnOperand/getOperand/getReceiver: [ArrayLiteral] [...]
# 319| getDesugared: [MethodCall] call to []
# 319| getReceiver: [ConstantReadAccess] Array
# 319| getArgument: [IntegerLiteral] 1
# 319| getArgument: [IntegerLiteral] 2
# 319| getArgument: [IntegerLiteral] 3
# 320| [AssignAddExpr] ... += ...
# 320| getDesugared: [StmtSequence] ...
# 320| getStmt: [AssignExpr] ... = ...
# 320| getAnOperand/getRightOperand: [MethodCall] call to bar
# 320| getReceiver: [MethodCall] call to foo
# 320| getReceiver: [SelfVariableAccess] self
# 320| getAnOperand/getRightOperand: [SelfVariableAccess] self
# 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 320| getStmt: [SetterMethodCall] call to []=
# 320| getStmt: [SetterMethodCall] call to count=
# 320| getReceiver: [LocalVariableAccess] __synth__0
# 320| getArgument: [LocalVariableAccess] __synth__1
# 320| getArgument: [LocalVariableAccess] __synth__2
# 320| getArgument: [LocalVariableAccess] __synth__3
# 320| getArgument: [LocalVariableAccess] __synth__4
# 320| getStmt: [AssignExpr] ... = ...
# 320| getAnOperand/getRightOperand: [IntegerLiteral] 0
# 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1
# 320| getStmt: [AssignExpr] ... = ...
# 320| getAnOperand/getRightOperand: [MethodCall] call to baz
# 320| getReceiver: [MethodCall] call to foo
# 320| getReceiver: [SelfVariableAccess] self
# 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2
# 320| getStmt: [AssignExpr] ... = ...
# 320| getAnOperand/getRightOperand: [AddExpr] ... + ...
# 320| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to boo
# 320| getReceiver: [MethodCall] call to foo
# 320| getReceiver: [SelfVariableAccess] self
# 320| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__3
# 320| getStmt: [AssignExpr] ... = ...
# 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__4
# 320| getAnOperand/getRightOperand: [MulExpr] ... * ...
# 320| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to []
# 320| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to count
# 320| getReceiver: [LocalVariableAccess] __synth__0
# 320| getArgument: [LocalVariableAccess] __synth__1
# 320| getArgument: [LocalVariableAccess] __synth__2
# 320| getArgument: [LocalVariableAccess] __synth__3
# 320| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
# 320| getStmt: [LocalVariableAccess] __synth__4
# 340| [ForExpr] for ... in ...
# 340| getDesugared: [MethodCall] call to each
# 340| getBlock: [BraceBlock] { ... }
# 340| getParameter: [SimpleParameter] __synth__0__1
# 340| getDefiningAccess: [LocalVariableAccess] __synth__0__1
# 340| getStmt: [AssignExpr] ... = ...
# 340| getDesugared: [StmtSequence] ...
# 340| getStmt: [AssignExpr] ... = ...
# 340| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 340| getAnOperand/getRightOperand: [SplatExpr] * ...
# 340| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] __synth__0__1
# 340| getStmt: [AssignExpr] ... = ...
# 340| getAnOperand/getLeftOperand: [LocalVariableAccess] x
# 340| getAnOperand/getRightOperand: [MethodCall] call to []
# 340| getReceiver: [LocalVariableAccess] __synth__0__1
# 340| getArgument: [IntegerLiteral] 0
# 340| getStmt: [AssignExpr] ... = ...
# 340| getAnOperand/getLeftOperand: [LocalVariableAccess] y
# 340| getAnOperand/getRightOperand: [MethodCall] call to []
# 340| getReceiver: [LocalVariableAccess] __synth__0__1
# 340| getArgument: [IntegerLiteral] 1
# 340| getStmt: [AssignExpr] ... = ...
# 340| getAnOperand/getLeftOperand: [LocalVariableAccess] z
# 340| getAnOperand/getRightOperand: [MethodCall] call to []
# 340| getReceiver: [LocalVariableAccess] __synth__0__1
# 340| getArgument: [IntegerLiteral] 2
# 340| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...)
# 341| getStmt: [MethodCall] call to foo
# 341| getReceiver: [SelfVariableAccess] self
# 341| getArgument: [LocalVariableAccess] x
# 341| getArgument: [LocalVariableAccess] y
# 341| getArgument: [LocalVariableAccess] z
# 340| getReceiver: [ArrayLiteral] [...]
# 340| getDesugared: [MethodCall] call to []
# 340| getReceiver: [ConstantReadAccess] Array
# 340| getArgument: [ArrayLiteral] [...]
# 340| getDesugared: [MethodCall] call to []
# 340| getReceiver: [ConstantReadAccess] Array
# 340| getArgument: [IntegerLiteral] 1
# 340| getArgument: [IntegerLiteral] 2
# 340| getArgument: [IntegerLiteral] 3
# 340| getArgument: [ArrayLiteral] [...]
# 340| getDesugared: [MethodCall] call to []
# 340| getReceiver: [ConstantReadAccess] Array
# 340| getArgument: [IntegerLiteral] 4
# 340| getArgument: [IntegerLiteral] 5
# 340| getArgument: [IntegerLiteral] 6
# 362| [MethodCall] call to empty?
# 362| getDesugared: [StmtSequence] ...
# 362| getStmt: [AssignExpr] ... = ...
# 362| getAnOperand/getRightOperand: [MethodCall] call to list
# 362| getReceiver: [SelfVariableAccess] self
# 362| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 362| getStmt: [IfExpr] if ...
# 362| getBranch/getThen: [NilLiteral] nil
# 362| getBranch/getElse: [MethodCall] call to empty?
# 362| getReceiver: [LocalVariableAccess] __synth__0__1
# 362| getCondition: [MethodCall] call to ==
# 362| getArgument: [LocalVariableAccess] __synth__0__1
# 362| getReceiver: [NilLiteral] nil
# 364| [MethodCall] call to bar
# 320| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 320| getStmt: [LocalVariableAccess] __synth__1
# 321| [AssignAddExpr] ... += ...
# 321| getDesugared: [StmtSequence] ...
# 321| getStmt: [AssignExpr] ... = ...
# 321| getAnOperand/getRightOperand: [MethodCall] call to foo
# 321| getReceiver: [SelfVariableAccess] self
# 321| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 321| getStmt: [SetterMethodCall] call to []=
# 321| getReceiver: [LocalVariableAccess] __synth__0
# 321| getArgument: [LocalVariableAccess] __synth__1
# 321| getArgument: [LocalVariableAccess] __synth__2
# 321| getStmt: [AssignExpr] ... = ...
# 321| getAnOperand/getRightOperand: [IntegerLiteral] 0
# 321| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1
# 321| getStmt: [AssignExpr] ... = ...
# 321| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2
# 321| getAnOperand/getRightOperand: [AddExpr] ... + ...
# 321| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to []
# 321| getReceiver: [LocalVariableAccess] __synth__0
# 321| getArgument: [LocalVariableAccess] __synth__1
# 321| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 321| getStmt: [LocalVariableAccess] __synth__2
# 322| [AssignMulExpr] ... *= ...
# 322| getDesugared: [StmtSequence] ...
# 322| getStmt: [AssignExpr] ... = ...
# 322| getAnOperand/getRightOperand: [MethodCall] call to bar
# 322| getReceiver: [MethodCall] call to foo
# 322| getReceiver: [SelfVariableAccess] self
# 322| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 322| getStmt: [SetterMethodCall] call to []=
# 322| getReceiver: [LocalVariableAccess] __synth__0
# 322| getArgument: [LocalVariableAccess] __synth__1
# 322| getArgument: [LocalVariableAccess] __synth__2
# 322| getArgument: [LocalVariableAccess] __synth__3
# 322| getArgument: [LocalVariableAccess] __synth__4
# 322| getStmt: [AssignExpr] ... = ...
# 322| getAnOperand/getRightOperand: [IntegerLiteral] 0
# 322| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1
# 322| getStmt: [AssignExpr] ... = ...
# 322| getAnOperand/getRightOperand: [MethodCall] call to baz
# 322| getReceiver: [MethodCall] call to foo
# 322| getReceiver: [SelfVariableAccess] self
# 322| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2
# 322| getStmt: [AssignExpr] ... = ...
# 322| getAnOperand/getRightOperand: [AddExpr] ... + ...
# 322| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to boo
# 322| getReceiver: [MethodCall] call to foo
# 322| getReceiver: [SelfVariableAccess] self
# 322| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 322| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__3
# 322| getStmt: [AssignExpr] ... = ...
# 322| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__4
# 322| getAnOperand/getRightOperand: [MulExpr] ... * ...
# 322| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to []
# 322| getReceiver: [LocalVariableAccess] __synth__0
# 322| getArgument: [LocalVariableAccess] __synth__1
# 322| getArgument: [LocalVariableAccess] __synth__2
# 322| getArgument: [LocalVariableAccess] __synth__3
# 322| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
# 322| getStmt: [LocalVariableAccess] __synth__4
# 342| [ForExpr] for ... in ...
# 342| getDesugared: [MethodCall] call to each
# 342| getBlock: [BraceBlock] { ... }
# 342| getParameter: [SimpleParameter] __synth__0__1
# 342| getDefiningAccess: [LocalVariableAccess] __synth__0__1
# 342| getStmt: [AssignExpr] ... = ...
# 342| getDesugared: [StmtSequence] ...
# 342| getStmt: [AssignExpr] ... = ...
# 342| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 342| getAnOperand/getRightOperand: [SplatExpr] * ...
# 342| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] __synth__0__1
# 342| getStmt: [AssignExpr] ... = ...
# 342| getAnOperand/getLeftOperand: [LocalVariableAccess] x
# 342| getAnOperand/getRightOperand: [MethodCall] call to []
# 342| getReceiver: [LocalVariableAccess] __synth__0__1
# 342| getArgument: [IntegerLiteral] 0
# 342| getStmt: [AssignExpr] ... = ...
# 342| getAnOperand/getLeftOperand: [LocalVariableAccess] y
# 342| getAnOperand/getRightOperand: [MethodCall] call to []
# 342| getReceiver: [LocalVariableAccess] __synth__0__1
# 342| getArgument: [IntegerLiteral] 1
# 342| getStmt: [AssignExpr] ... = ...
# 342| getAnOperand/getLeftOperand: [LocalVariableAccess] z
# 342| getAnOperand/getRightOperand: [MethodCall] call to []
# 342| getReceiver: [LocalVariableAccess] __synth__0__1
# 342| getArgument: [IntegerLiteral] 2
# 342| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...)
# 343| getStmt: [MethodCall] call to foo
# 343| getReceiver: [SelfVariableAccess] self
# 343| getArgument: [LocalVariableAccess] x
# 343| getArgument: [LocalVariableAccess] y
# 343| getArgument: [LocalVariableAccess] z
# 342| getReceiver: [ArrayLiteral] [...]
# 342| getDesugared: [MethodCall] call to []
# 342| getReceiver: [ConstantReadAccess] Array
# 342| getArgument: [ArrayLiteral] [...]
# 342| getDesugared: [MethodCall] call to []
# 342| getReceiver: [ConstantReadAccess] Array
# 342| getArgument: [IntegerLiteral] 1
# 342| getArgument: [IntegerLiteral] 2
# 342| getArgument: [IntegerLiteral] 3
# 342| getArgument: [ArrayLiteral] [...]
# 342| getDesugared: [MethodCall] call to []
# 342| getReceiver: [ConstantReadAccess] Array
# 342| getArgument: [IntegerLiteral] 4
# 342| getArgument: [IntegerLiteral] 5
# 342| getArgument: [IntegerLiteral] 6
# 364| [MethodCall] call to empty?
# 364| getDesugared: [StmtSequence] ...
# 364| getStmt: [AssignExpr] ... = ...
# 364| getAnOperand/getRightOperand: [MethodCall] call to foo
# 364| getAnOperand/getRightOperand: [MethodCall] call to list
# 364| getReceiver: [SelfVariableAccess] self
# 364| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 364| getStmt: [IfExpr] if ...
# 364| getBranch/getThen: [NilLiteral] nil
# 364| getBranch/getElse: [MethodCall] call to bar
# 364| getBranch/getElse: [MethodCall] call to empty?
# 364| getReceiver: [LocalVariableAccess] __synth__0__1
# 364| getArgument: [IntegerLiteral] 1
# 364| getArgument: [IntegerLiteral] 2
# 364| getBlock: [BraceBlock] { ... }
# 364| getParameter: [SimpleParameter] x
# 364| getDefiningAccess: [LocalVariableAccess] x
# 364| getStmt: [LocalVariableAccess] x
# 364| getCondition: [MethodCall] call to ==
# 364| getArgument: [LocalVariableAccess] __synth__0__1
# 364| getReceiver: [NilLiteral] nil
# 366| [MethodCall] call to bar
# 366| getDesugared: [StmtSequence] ...
# 366| getStmt: [AssignExpr] ... = ...
# 366| getAnOperand/getRightOperand: [MethodCall] call to foo
# 366| getReceiver: [SelfVariableAccess] self
# 366| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 366| getStmt: [IfExpr] if ...
# 366| getBranch/getThen: [NilLiteral] nil
# 366| getBranch/getElse: [MethodCall] call to bar
# 366| getReceiver: [LocalVariableAccess] __synth__0__1
# 366| getArgument: [IntegerLiteral] 1
# 366| getArgument: [IntegerLiteral] 2
# 366| getBlock: [BraceBlock] { ... }
# 366| getParameter: [SimpleParameter] x
# 366| getDefiningAccess: [LocalVariableAccess] x
# 366| getStmt: [LocalVariableAccess] x
# 366| getCondition: [MethodCall] call to ==
# 366| getArgument: [LocalVariableAccess] __synth__0__1
# 366| getReceiver: [NilLiteral] nil
control/cases.rb:
# 90| [ArrayLiteral] %w(...)
# 90| getDesugared: [MethodCall] call to []

File diff suppressed because it is too large Load Diff

View File

@@ -10,76 +10,76 @@ exprValue
| calls/calls.rb:26:7:26:7 | 1 | 1 | int |
| calls/calls.rb:36:9:36:11 | 100 | 100 | int |
| calls/calls.rb:36:14:36:16 | 200 | 200 | int |
| calls/calls.rb:278:5:278:8 | :blah | :blah | symbol |
| calls/calls.rb:279:5:279:8 | :blah | :blah | symbol |
| calls/calls.rb:288:11:288:16 | "blah" | blah | string |
| calls/calls.rb:289:11:289:11 | 1 | 1 | int |
| calls/calls.rb:289:14:289:14 | 2 | 2 | int |
| calls/calls.rb:289:17:289:17 | 3 | 3 | int |
| calls/calls.rb:290:21:290:21 | 1 | 1 | int |
| calls/calls.rb:291:22:291:22 | 2 | 2 | int |
| calls/calls.rb:292:11:292:11 | 4 | 4 | int |
| calls/calls.rb:292:14:292:14 | 5 | 5 | int |
| calls/calls.rb:292:26:292:28 | 100 | 100 | int |
| calls/calls.rb:293:11:293:11 | 6 | 6 | int |
| calls/calls.rb:293:14:293:14 | 7 | 7 | int |
| calls/calls.rb:293:27:293:29 | 200 | 200 | int |
| calls/calls.rb:311:6:311:6 | 1 | 1 | int |
| calls/calls.rb:314:1:314:8 | __synth__0 | 10 | int |
| calls/calls.rb:314:12:314:13 | 10 | 10 | int |
| calls/calls.rb:315:1:315:6 | __synth__0 | 10 | int |
| calls/calls.rb:315:5:315:5 | 0 | 0 | int |
| calls/calls.rb:315:10:315:11 | 10 | 10 | int |
| calls/calls.rb:316:1:316:8 | 0 | 0 | int |
| calls/calls.rb:316:12:316:19 | 1 | 1 | int |
| calls/calls.rb:316:12:316:19 | -2 | -2 | int |
| calls/calls.rb:316:22:316:27 | -1 | -1 | int |
| calls/calls.rb:316:26:316:26 | 4 | 4 | int |
| calls/calls.rb:316:32:316:32 | 1 | 1 | int |
| calls/calls.rb:316:35:316:35 | 2 | 2 | int |
| calls/calls.rb:316:38:316:38 | 3 | 3 | int |
| calls/calls.rb:316:41:316:41 | 4 | 4 | int |
| calls/calls.rb:317:1:317:1 | 0 | 0 | int |
| calls/calls.rb:317:5:317:10 | 1 | 1 | int |
| calls/calls.rb:317:5:317:10 | -1 | -1 | int |
| calls/calls.rb:317:9:317:9 | 5 | 5 | int |
| calls/calls.rb:317:15:317:15 | 1 | 1 | int |
| calls/calls.rb:317:18:317:18 | 2 | 2 | int |
| calls/calls.rb:317:21:317:21 | 3 | 3 | int |
| calls/calls.rb:318:15:318:15 | 1 | 1 | int |
| calls/calls.rb:319:5:319:5 | 0 | 0 | int |
| calls/calls.rb:319:5:319:5 | __synth__1 | 0 | int |
| calls/calls.rb:319:5:319:5 | __synth__1 | 0 | int |
| calls/calls.rb:319:11:319:11 | 1 | 1 | int |
| calls/calls.rb:320:9:320:9 | 0 | 0 | int |
| calls/calls.rb:320:9:320:9 | __synth__1 | 0 | int |
| calls/calls.rb:320:9:320:9 | __synth__1 | 0 | int |
| calls/calls.rb:320:31:320:31 | 1 | 1 | int |
| calls/calls.rb:320:37:320:37 | 2 | 2 | int |
| calls/calls.rb:328:31:328:37 | "error" | error | string |
| calls/calls.rb:340:5:340:5 | 0 | 0 | int |
| calls/calls.rb:340:8:340:8 | 1 | 1 | int |
| calls/calls.rb:340:11:340:11 | 2 | 2 | int |
| calls/calls.rb:340:18:340:18 | 1 | 1 | int |
| calls/calls.rb:340:20:340:20 | 2 | 2 | int |
| calls/calls.rb:340:22:340:22 | 3 | 3 | int |
| calls/calls.rb:340:27:340:27 | 4 | 4 | int |
| calls/calls.rb:340:29:340:29 | 5 | 5 | int |
| calls/calls.rb:340:31:340:31 | 6 | 6 | int |
| calls/calls.rb:344:5:344:5 | :x | :x | symbol |
| calls/calls.rb:344:8:344:9 | 42 | 42 | int |
| calls/calls.rb:345:5:345:5 | :x | :x | symbol |
| calls/calls.rb:345:9:345:13 | :novar | :novar | symbol |
| calls/calls.rb:346:5:346:5 | :X | :X | symbol |
| calls/calls.rb:280:5:280:8 | :blah | :blah | symbol |
| calls/calls.rb:281:5:281:8 | :blah | :blah | symbol |
| calls/calls.rb:290:11:290:16 | "blah" | blah | string |
| calls/calls.rb:291:11:291:11 | 1 | 1 | int |
| calls/calls.rb:291:14:291:14 | 2 | 2 | int |
| calls/calls.rb:291:17:291:17 | 3 | 3 | int |
| calls/calls.rb:292:21:292:21 | 1 | 1 | int |
| calls/calls.rb:293:22:293:22 | 2 | 2 | int |
| calls/calls.rb:294:11:294:11 | 4 | 4 | int |
| calls/calls.rb:294:14:294:14 | 5 | 5 | int |
| calls/calls.rb:294:26:294:28 | 100 | 100 | int |
| calls/calls.rb:295:11:295:11 | 6 | 6 | int |
| calls/calls.rb:295:14:295:14 | 7 | 7 | int |
| calls/calls.rb:295:27:295:29 | 200 | 200 | int |
| calls/calls.rb:313:6:313:6 | 1 | 1 | int |
| calls/calls.rb:316:1:316:8 | __synth__0 | 10 | int |
| calls/calls.rb:316:12:316:13 | 10 | 10 | int |
| calls/calls.rb:317:1:317:6 | __synth__0 | 10 | int |
| calls/calls.rb:317:5:317:5 | 0 | 0 | int |
| calls/calls.rb:317:10:317:11 | 10 | 10 | int |
| calls/calls.rb:318:1:318:8 | 0 | 0 | int |
| calls/calls.rb:318:12:318:19 | 1 | 1 | int |
| calls/calls.rb:318:12:318:19 | -2 | -2 | int |
| calls/calls.rb:318:22:318:27 | -1 | -1 | int |
| calls/calls.rb:318:26:318:26 | 4 | 4 | int |
| calls/calls.rb:318:32:318:32 | 1 | 1 | int |
| calls/calls.rb:318:35:318:35 | 2 | 2 | int |
| calls/calls.rb:318:38:318:38 | 3 | 3 | int |
| calls/calls.rb:318:41:318:41 | 4 | 4 | int |
| calls/calls.rb:319:1:319:1 | 0 | 0 | int |
| calls/calls.rb:319:5:319:10 | 1 | 1 | int |
| calls/calls.rb:319:5:319:10 | -1 | -1 | int |
| calls/calls.rb:319:9:319:9 | 5 | 5 | int |
| calls/calls.rb:319:15:319:15 | 1 | 1 | int |
| calls/calls.rb:319:18:319:18 | 2 | 2 | int |
| calls/calls.rb:319:21:319:21 | 3 | 3 | int |
| calls/calls.rb:320:15:320:15 | 1 | 1 | int |
| calls/calls.rb:321:5:321:5 | 0 | 0 | int |
| calls/calls.rb:321:5:321:5 | __synth__1 | 0 | int |
| calls/calls.rb:321:5:321:5 | __synth__1 | 0 | int |
| calls/calls.rb:321:11:321:11 | 1 | 1 | int |
| calls/calls.rb:322:9:322:9 | 0 | 0 | int |
| calls/calls.rb:322:9:322:9 | __synth__1 | 0 | int |
| calls/calls.rb:322:9:322:9 | __synth__1 | 0 | int |
| calls/calls.rb:322:31:322:31 | 1 | 1 | int |
| calls/calls.rb:322:37:322:37 | 2 | 2 | int |
| calls/calls.rb:330:31:330:37 | "error" | error | string |
| calls/calls.rb:342:5:342:5 | 0 | 0 | int |
| calls/calls.rb:342:8:342:8 | 1 | 1 | int |
| calls/calls.rb:342:11:342:11 | 2 | 2 | int |
| calls/calls.rb:342:18:342:18 | 1 | 1 | int |
| calls/calls.rb:342:20:342:20 | 2 | 2 | int |
| calls/calls.rb:342:22:342:22 | 3 | 3 | int |
| calls/calls.rb:342:27:342:27 | 4 | 4 | int |
| calls/calls.rb:342:29:342:29 | 5 | 5 | int |
| calls/calls.rb:342:31:342:31 | 6 | 6 | int |
| calls/calls.rb:346:5:346:5 | :x | :x | symbol |
| calls/calls.rb:346:8:346:9 | 42 | 42 | int |
| calls/calls.rb:347:5:347:5 | :X | :X | symbol |
| calls/calls.rb:350:5:350:5 | 1 | 1 | int |
| calls/calls.rb:362:1:362:4 | nil | nil | nil |
| calls/calls.rb:362:5:362:6 | nil | nil | nil |
| calls/calls.rb:364:1:364:3 | nil | nil | nil |
| calls/calls.rb:364:4:364:5 | nil | nil | nil |
| calls/calls.rb:364:10:364:10 | 1 | 1 | int |
| calls/calls.rb:364:12:364:12 | 2 | 2 | int |
| calls/calls.rb:347:5:347:5 | :x | :x | symbol |
| calls/calls.rb:347:9:347:13 | :novar | :novar | symbol |
| calls/calls.rb:348:5:348:5 | :X | :X | symbol |
| calls/calls.rb:348:8:348:9 | 42 | 42 | int |
| calls/calls.rb:349:5:349:5 | :X | :X | symbol |
| calls/calls.rb:352:5:352:5 | 1 | 1 | int |
| calls/calls.rb:364:1:364:4 | nil | nil | nil |
| calls/calls.rb:364:5:364:6 | nil | nil | nil |
| calls/calls.rb:366:1:366:3 | nil | nil | nil |
| calls/calls.rb:366:4:366:5 | nil | nil | nil |
| calls/calls.rb:366:10:366:10 | 1 | 1 | int |
| calls/calls.rb:366:12:366:12 | 2 | 2 | int |
| constants/constants.rb:3:19:3:27 | "const_a" | const_a | string |
| constants/constants.rb:6:15:6:23 | "const_b" | const_b | string |
| constants/constants.rb:17:12:17:18 | "Hello" | Hello | string |
@@ -920,76 +920,76 @@ exprCfgNodeValue
| calls/calls.rb:26:7:26:7 | 1 | 1 | int |
| calls/calls.rb:36:9:36:11 | 100 | 100 | int |
| calls/calls.rb:36:14:36:16 | 200 | 200 | int |
| calls/calls.rb:278:5:278:8 | :blah | :blah | symbol |
| calls/calls.rb:279:5:279:8 | :blah | :blah | symbol |
| calls/calls.rb:288:11:288:16 | "blah" | blah | string |
| calls/calls.rb:289:11:289:11 | 1 | 1 | int |
| calls/calls.rb:289:14:289:14 | 2 | 2 | int |
| calls/calls.rb:289:17:289:17 | 3 | 3 | int |
| calls/calls.rb:290:21:290:21 | 1 | 1 | int |
| calls/calls.rb:291:22:291:22 | 2 | 2 | int |
| calls/calls.rb:292:11:292:11 | 4 | 4 | int |
| calls/calls.rb:292:14:292:14 | 5 | 5 | int |
| calls/calls.rb:292:26:292:28 | 100 | 100 | int |
| calls/calls.rb:293:11:293:11 | 6 | 6 | int |
| calls/calls.rb:293:14:293:14 | 7 | 7 | int |
| calls/calls.rb:293:27:293:29 | 200 | 200 | int |
| calls/calls.rb:311:6:311:6 | 1 | 1 | int |
| calls/calls.rb:314:1:314:8 | __synth__0 | 10 | int |
| calls/calls.rb:314:12:314:13 | 10 | 10 | int |
| calls/calls.rb:315:1:315:6 | __synth__0 | 10 | int |
| calls/calls.rb:315:5:315:5 | 0 | 0 | int |
| calls/calls.rb:315:10:315:11 | 10 | 10 | int |
| calls/calls.rb:316:1:316:8 | 0 | 0 | int |
| calls/calls.rb:316:12:316:19 | 1 | 1 | int |
| calls/calls.rb:316:12:316:19 | -2 | -2 | int |
| calls/calls.rb:316:22:316:27 | -1 | -1 | int |
| calls/calls.rb:316:26:316:26 | 4 | 4 | int |
| calls/calls.rb:316:32:316:32 | 1 | 1 | int |
| calls/calls.rb:316:35:316:35 | 2 | 2 | int |
| calls/calls.rb:316:38:316:38 | 3 | 3 | int |
| calls/calls.rb:316:41:316:41 | 4 | 4 | int |
| calls/calls.rb:317:1:317:1 | 0 | 0 | int |
| calls/calls.rb:317:5:317:10 | 1 | 1 | int |
| calls/calls.rb:317:5:317:10 | -1 | -1 | int |
| calls/calls.rb:317:9:317:9 | 5 | 5 | int |
| calls/calls.rb:317:15:317:15 | 1 | 1 | int |
| calls/calls.rb:317:18:317:18 | 2 | 2 | int |
| calls/calls.rb:317:21:317:21 | 3 | 3 | int |
| calls/calls.rb:318:15:318:15 | 1 | 1 | int |
| calls/calls.rb:319:5:319:5 | 0 | 0 | int |
| calls/calls.rb:319:5:319:5 | __synth__1 | 0 | int |
| calls/calls.rb:319:5:319:5 | __synth__1 | 0 | int |
| calls/calls.rb:319:11:319:11 | 1 | 1 | int |
| calls/calls.rb:320:9:320:9 | 0 | 0 | int |
| calls/calls.rb:320:9:320:9 | __synth__1 | 0 | int |
| calls/calls.rb:320:9:320:9 | __synth__1 | 0 | int |
| calls/calls.rb:320:31:320:31 | 1 | 1 | int |
| calls/calls.rb:320:37:320:37 | 2 | 2 | int |
| calls/calls.rb:328:31:328:37 | "error" | error | string |
| calls/calls.rb:340:5:340:5 | 0 | 0 | int |
| calls/calls.rb:340:8:340:8 | 1 | 1 | int |
| calls/calls.rb:340:11:340:11 | 2 | 2 | int |
| calls/calls.rb:340:18:340:18 | 1 | 1 | int |
| calls/calls.rb:340:20:340:20 | 2 | 2 | int |
| calls/calls.rb:340:22:340:22 | 3 | 3 | int |
| calls/calls.rb:340:27:340:27 | 4 | 4 | int |
| calls/calls.rb:340:29:340:29 | 5 | 5 | int |
| calls/calls.rb:340:31:340:31 | 6 | 6 | int |
| calls/calls.rb:344:5:344:5 | :x | :x | symbol |
| calls/calls.rb:344:8:344:9 | 42 | 42 | int |
| calls/calls.rb:345:5:345:5 | :x | :x | symbol |
| calls/calls.rb:345:9:345:13 | :novar | :novar | symbol |
| calls/calls.rb:346:5:346:5 | :X | :X | symbol |
| calls/calls.rb:280:5:280:8 | :blah | :blah | symbol |
| calls/calls.rb:281:5:281:8 | :blah | :blah | symbol |
| calls/calls.rb:290:11:290:16 | "blah" | blah | string |
| calls/calls.rb:291:11:291:11 | 1 | 1 | int |
| calls/calls.rb:291:14:291:14 | 2 | 2 | int |
| calls/calls.rb:291:17:291:17 | 3 | 3 | int |
| calls/calls.rb:292:21:292:21 | 1 | 1 | int |
| calls/calls.rb:293:22:293:22 | 2 | 2 | int |
| calls/calls.rb:294:11:294:11 | 4 | 4 | int |
| calls/calls.rb:294:14:294:14 | 5 | 5 | int |
| calls/calls.rb:294:26:294:28 | 100 | 100 | int |
| calls/calls.rb:295:11:295:11 | 6 | 6 | int |
| calls/calls.rb:295:14:295:14 | 7 | 7 | int |
| calls/calls.rb:295:27:295:29 | 200 | 200 | int |
| calls/calls.rb:313:6:313:6 | 1 | 1 | int |
| calls/calls.rb:316:1:316:8 | __synth__0 | 10 | int |
| calls/calls.rb:316:12:316:13 | 10 | 10 | int |
| calls/calls.rb:317:1:317:6 | __synth__0 | 10 | int |
| calls/calls.rb:317:5:317:5 | 0 | 0 | int |
| calls/calls.rb:317:10:317:11 | 10 | 10 | int |
| calls/calls.rb:318:1:318:8 | 0 | 0 | int |
| calls/calls.rb:318:12:318:19 | 1 | 1 | int |
| calls/calls.rb:318:12:318:19 | -2 | -2 | int |
| calls/calls.rb:318:22:318:27 | -1 | -1 | int |
| calls/calls.rb:318:26:318:26 | 4 | 4 | int |
| calls/calls.rb:318:32:318:32 | 1 | 1 | int |
| calls/calls.rb:318:35:318:35 | 2 | 2 | int |
| calls/calls.rb:318:38:318:38 | 3 | 3 | int |
| calls/calls.rb:318:41:318:41 | 4 | 4 | int |
| calls/calls.rb:319:1:319:1 | 0 | 0 | int |
| calls/calls.rb:319:5:319:10 | 1 | 1 | int |
| calls/calls.rb:319:5:319:10 | -1 | -1 | int |
| calls/calls.rb:319:9:319:9 | 5 | 5 | int |
| calls/calls.rb:319:15:319:15 | 1 | 1 | int |
| calls/calls.rb:319:18:319:18 | 2 | 2 | int |
| calls/calls.rb:319:21:319:21 | 3 | 3 | int |
| calls/calls.rb:320:15:320:15 | 1 | 1 | int |
| calls/calls.rb:321:5:321:5 | 0 | 0 | int |
| calls/calls.rb:321:5:321:5 | __synth__1 | 0 | int |
| calls/calls.rb:321:5:321:5 | __synth__1 | 0 | int |
| calls/calls.rb:321:11:321:11 | 1 | 1 | int |
| calls/calls.rb:322:9:322:9 | 0 | 0 | int |
| calls/calls.rb:322:9:322:9 | __synth__1 | 0 | int |
| calls/calls.rb:322:9:322:9 | __synth__1 | 0 | int |
| calls/calls.rb:322:31:322:31 | 1 | 1 | int |
| calls/calls.rb:322:37:322:37 | 2 | 2 | int |
| calls/calls.rb:330:31:330:37 | "error" | error | string |
| calls/calls.rb:342:5:342:5 | 0 | 0 | int |
| calls/calls.rb:342:8:342:8 | 1 | 1 | int |
| calls/calls.rb:342:11:342:11 | 2 | 2 | int |
| calls/calls.rb:342:18:342:18 | 1 | 1 | int |
| calls/calls.rb:342:20:342:20 | 2 | 2 | int |
| calls/calls.rb:342:22:342:22 | 3 | 3 | int |
| calls/calls.rb:342:27:342:27 | 4 | 4 | int |
| calls/calls.rb:342:29:342:29 | 5 | 5 | int |
| calls/calls.rb:342:31:342:31 | 6 | 6 | int |
| calls/calls.rb:346:5:346:5 | :x | :x | symbol |
| calls/calls.rb:346:8:346:9 | 42 | 42 | int |
| calls/calls.rb:347:5:347:5 | :X | :X | symbol |
| calls/calls.rb:350:5:350:5 | 1 | 1 | int |
| calls/calls.rb:362:1:362:4 | nil | nil | nil |
| calls/calls.rb:362:5:362:6 | nil | nil | nil |
| calls/calls.rb:364:1:364:3 | nil | nil | nil |
| calls/calls.rb:364:4:364:5 | nil | nil | nil |
| calls/calls.rb:364:10:364:10 | 1 | 1 | int |
| calls/calls.rb:364:12:364:12 | 2 | 2 | int |
| calls/calls.rb:347:5:347:5 | :x | :x | symbol |
| calls/calls.rb:347:9:347:13 | :novar | :novar | symbol |
| calls/calls.rb:348:5:348:5 | :X | :X | symbol |
| calls/calls.rb:348:8:348:9 | 42 | 42 | int |
| calls/calls.rb:349:5:349:5 | :X | :X | symbol |
| calls/calls.rb:352:5:352:5 | 1 | 1 | int |
| calls/calls.rb:364:1:364:4 | nil | nil | nil |
| calls/calls.rb:364:5:364:6 | nil | nil | nil |
| calls/calls.rb:366:1:366:3 | nil | nil | nil |
| calls/calls.rb:366:4:366:5 | nil | nil | nil |
| calls/calls.rb:366:10:366:10 | 1 | 1 | int |
| calls/calls.rb:366:12:366:12 | 2 | 2 | int |
| constants/constants.rb:3:19:3:27 | "const_a" | const_a | string |
| constants/constants.rb:6:15:6:23 | "const_b" | const_b | string |
| constants/constants.rb:17:12:17:18 | "Hello" | Hello | string |

View File

@@ -4,27 +4,27 @@ blockArguments
splatExpr
| calls.rb:270:5:270:8 | * ... | calls.rb:270:6:270:8 | call to bar |
| calls.rb:271:5:271:11 | * ... | calls.rb:271:6:271:11 | call to bar |
| calls.rb:316:31:316:42 | * ... | calls.rb:316:31:316:42 | [...] |
| calls.rb:317:14:317:22 | * ... | calls.rb:317:14:317:22 | [...] |
| calls.rb:340:1:342:3 | * ... | calls.rb:340:1:342:3 | __synth__0__1 |
| calls.rb:318:31:318:42 | * ... | calls.rb:318:31:318:42 | [...] |
| calls.rb:319:14:319:22 | * ... | calls.rb:319:14:319:22 | [...] |
| calls.rb:342:1:344:3 | * ... | calls.rb:342:1:344:3 | __synth__0__1 |
hashSplatExpr
| calls.rb:274:5:274:9 | ** ... | calls.rb:274:7:274:9 | call to bar |
| calls.rb:275:5:275:12 | ** ... | calls.rb:275:7:275:12 | call to bar |
| calls.rb:275:5:275:9 | ** ... | calls.rb:275:7:275:9 | call to bar |
| calls.rb:276:5:276:12 | ** ... | calls.rb:276:7:276:12 | call to bar |
keywordArguments
| calls.rb:249:3:249:12 | Pair | calls.rb:249:3:249:5 | call to foo | calls.rb:249:10:249:12 | call to bar |
| calls.rb:249:15:249:30 | Pair | calls.rb:249:15:249:20 | call to foo | calls.rb:249:25:249:30 | call to bar |
| calls.rb:278:5:278:13 | Pair | calls.rb:278:5:278:8 | :blah | calls.rb:278:11:278:13 | call to bar |
| calls.rb:279:5:279:16 | Pair | calls.rb:279:5:279:8 | :blah | calls.rb:279:11:279:16 | call to bar |
| calls.rb:344:5:344:9 | Pair | calls.rb:344:5:344:5 | :x | calls.rb:344:8:344:9 | 42 |
| calls.rb:345:5:345:6 | Pair | calls.rb:345:5:345:5 | :x | calls.rb:345:5:345:5 | x |
| calls.rb:345:9:345:14 | Pair | calls.rb:345:9:345:13 | :novar | calls.rb:345:9:345:13 | call to novar |
| calls.rb:346:5:346:9 | Pair | calls.rb:346:5:346:5 | :X | calls.rb:346:8:346:9 | 42 |
| calls.rb:347:5:347:6 | Pair | calls.rb:347:5:347:5 | :X | calls.rb:347:5:347:5 | X |
| calls.rb:280:5:280:13 | Pair | calls.rb:280:5:280:8 | :blah | calls.rb:280:11:280:13 | call to bar |
| calls.rb:281:5:281:16 | Pair | calls.rb:281:5:281:8 | :blah | calls.rb:281:11:281:16 | call to bar |
| calls.rb:346:5:346:9 | Pair | calls.rb:346:5:346:5 | :x | calls.rb:346:8:346:9 | 42 |
| calls.rb:347:5:347:6 | Pair | calls.rb:347:5:347:5 | :x | calls.rb:347:5:347:5 | x |
| calls.rb:347:9:347:14 | Pair | calls.rb:347:9:347:13 | :novar | calls.rb:347:9:347:13 | call to novar |
| calls.rb:348:5:348:9 | Pair | calls.rb:348:5:348:5 | :X | calls.rb:348:8:348:9 | 42 |
| calls.rb:349:5:349:6 | Pair | calls.rb:349:5:349:5 | :X | calls.rb:349:5:349:5 | X |
keywordArgumentsByKeyword
| calls.rb:278:1:278:14 | call to foo | blah | calls.rb:278:11:278:13 | call to bar |
| calls.rb:279:1:279:17 | call to foo | blah | calls.rb:279:11:279:16 | call to bar |
| calls.rb:344:1:344:10 | call to foo | x | calls.rb:344:8:344:9 | 42 |
| calls.rb:345:1:345:15 | call to foo | novar | calls.rb:345:9:345:13 | call to novar |
| calls.rb:345:1:345:15 | call to foo | x | calls.rb:345:5:345:5 | x |
| calls.rb:346:1:346:10 | call to foo | X | calls.rb:346:8:346:9 | 42 |
| calls.rb:347:1:347:7 | call to foo | X | calls.rb:347:5:347:5 | X |
| calls.rb:280:1:280:14 | call to foo | blah | calls.rb:280:11:280:13 | call to bar |
| calls.rb:281:1:281:17 | call to foo | blah | calls.rb:281:11:281:16 | call to bar |
| calls.rb:346:1:346:10 | call to foo | x | calls.rb:346:8:346:9 | 42 |
| calls.rb:347:1:347:15 | call to foo | novar | calls.rb:347:9:347:13 | call to novar |
| calls.rb:347:1:347:15 | call to foo | x | calls.rb:347:5:347:5 | x |
| calls.rb:348:1:348:10 | call to foo | X | calls.rb:348:8:348:9 | 42 |
| calls.rb:349:1:349:7 | call to foo | X | calls.rb:349:5:349:5 | X |

View File

@@ -1,9 +1,11 @@
callsWithNoReceiverArgumentsOrBlock
| calls.rb:31:3:31:7 | yield ... | (none) |
| calls.rb:286:5:286:9 | super call to my_method | my_method |
| calls.rb:287:5:287:11 | super call to my_method | my_method |
| calls.rb:305:5:305:9 | super call to another_method | another_method |
| calls.rb:345:9:345:13 | call to novar | novar |
| calls.rb:272:5:272:5 | * ... | * |
| calls.rb:277:5:277:6 | ** ... | ** |
| calls.rb:288:5:288:9 | super call to my_method | my_method |
| calls.rb:289:5:289:11 | super call to my_method | my_method |
| calls.rb:307:5:307:9 | super call to another_method | another_method |
| calls.rb:347:9:347:13 | call to novar | novar |
callsWithArguments
| calls.rb:14:1:14:11 | call to foo | foo | 0 | calls.rb:14:5:14:5 | 0 |
| calls.rb:14:1:14:11 | call to foo | foo | 1 | calls.rb:14:8:14:8 | 1 |
@@ -30,96 +32,98 @@ callsWithArguments
| calls.rb:268:1:268:6 | call to foo | foo | 0 | calls.rb:268:5:268:5 | &... |
| calls.rb:270:1:270:9 | call to foo | foo | 0 | calls.rb:270:5:270:8 | * ... |
| calls.rb:271:1:271:12 | call to foo | foo | 0 | calls.rb:271:5:271:11 | * ... |
| calls.rb:274:1:274:10 | call to foo | foo | 0 | calls.rb:274:5:274:9 | ** ... |
| calls.rb:275:1:275:13 | call to foo | foo | 0 | calls.rb:275:5:275:12 | ** ... |
| calls.rb:278:1:278:14 | call to foo | foo | 0 | calls.rb:278:5:278:13 | Pair |
| calls.rb:279:1:279:17 | call to foo | foo | 0 | calls.rb:279:5:279:16 | Pair |
| calls.rb:288:5:288:16 | super call to my_method | my_method | 0 | calls.rb:288:11:288:16 | "blah" |
| calls.rb:289:5:289:17 | super call to my_method | my_method | 0 | calls.rb:289:11:289:11 | 1 |
| calls.rb:289:5:289:17 | super call to my_method | my_method | 1 | calls.rb:289:14:289:14 | 2 |
| calls.rb:289:5:289:17 | super call to my_method | my_method | 2 | calls.rb:289:17:289:17 | 3 |
| calls.rb:290:17:290:21 | ... + ... | + | 0 | calls.rb:290:21:290:21 | 1 |
| calls.rb:291:18:291:22 | ... * ... | * | 0 | calls.rb:291:22:291:22 | 2 |
| calls.rb:292:5:292:30 | super call to my_method | my_method | 0 | calls.rb:292:11:292:11 | 4 |
| calls.rb:292:5:292:30 | super call to my_method | my_method | 1 | calls.rb:292:14:292:14 | 5 |
| calls.rb:292:22:292:28 | ... + ... | + | 0 | calls.rb:292:26:292:28 | 100 |
| calls.rb:293:5:293:33 | super call to my_method | my_method | 0 | calls.rb:293:11:293:11 | 6 |
| calls.rb:293:5:293:33 | super call to my_method | my_method | 1 | calls.rb:293:14:293:14 | 7 |
| calls.rb:293:23:293:29 | ... + ... | + | 0 | calls.rb:293:27:293:29 | 200 |
| calls.rb:311:1:311:7 | call to call | call | 0 | calls.rb:311:6:311:6 | 1 |
| calls.rb:314:1:314:8 | call to foo= | foo= | 0 | calls.rb:314:12:314:13 | ... = ... |
| calls.rb:315:1:315:6 | ...[...] | [] | 0 | calls.rb:315:5:315:5 | 0 |
| calls.rb:315:1:315:6 | call to []= | []= | 0 | calls.rb:315:5:315:5 | 0 |
| calls.rb:315:1:315:6 | call to []= | []= | 1 | calls.rb:315:10:315:11 | ... = ... |
| calls.rb:316:1:316:8 | call to [] | [] | 0 | calls.rb:316:1:316:8 | 0 |
| calls.rb:316:1:316:8 | call to foo= | foo= | 0 | calls.rb:316:1:316:8 | ... = ... |
| calls.rb:316:12:316:19 | call to [] | [] | 0 | calls.rb:316:12:316:19 | _ .. _ |
| calls.rb:316:12:316:19 | call to bar= | bar= | 0 | calls.rb:316:12:316:19 | ... = ... |
| calls.rb:316:22:316:27 | ...[...] | [] | 0 | calls.rb:316:26:316:26 | 4 |
| calls.rb:316:22:316:27 | call to [] | [] | 0 | calls.rb:316:22:316:27 | -1 |
| calls.rb:316:22:316:27 | call to []= | []= | 0 | calls.rb:316:26:316:26 | 4 |
| calls.rb:316:22:316:27 | call to []= | []= | 1 | calls.rb:316:22:316:27 | ... = ... |
| calls.rb:316:31:316:42 | call to [] | [] | 0 | calls.rb:316:32:316:32 | 1 |
| calls.rb:316:31:316:42 | call to [] | [] | 1 | calls.rb:316:35:316:35 | 2 |
| calls.rb:316:31:316:42 | call to [] | [] | 2 | calls.rb:316:38:316:38 | 3 |
| calls.rb:316:31:316:42 | call to [] | [] | 3 | calls.rb:316:41:316:41 | 4 |
| calls.rb:317:1:317:1 | call to [] | [] | 0 | calls.rb:317:1:317:1 | 0 |
| calls.rb:317:5:317:10 | ...[...] | [] | 0 | calls.rb:317:9:317:9 | 5 |
| calls.rb:317:5:317:10 | call to [] | [] | 0 | calls.rb:317:5:317:10 | _ .. _ |
| calls.rb:317:5:317:10 | call to []= | []= | 0 | calls.rb:317:9:317:9 | 5 |
| calls.rb:317:5:317:10 | call to []= | []= | 1 | calls.rb:317:5:317:10 | ... = ... |
| calls.rb:317:14:317:22 | call to [] | [] | 0 | calls.rb:317:15:317:15 | 1 |
| calls.rb:317:14:317:22 | call to [] | [] | 1 | calls.rb:317:18:317:18 | 2 |
| calls.rb:317:14:317:22 | call to [] | [] | 2 | calls.rb:317:21:317:21 | 3 |
| calls.rb:318:1:318:10 | call to count= | count= | 1 | calls.rb:318:12:318:13 | __synth__1 |
| calls.rb:318:12:318:13 | ... + ... | + | 0 | calls.rb:318:15:318:15 | 1 |
| calls.rb:319:1:319:6 | ...[...] | [] | 0 | calls.rb:319:5:319:5 | 0 |
| calls.rb:319:1:319:6 | call to [] | [] | 0 | calls.rb:319:5:319:5 | __synth__1 |
| calls.rb:319:1:319:6 | call to []= | []= | 0 | calls.rb:319:5:319:5 | __synth__1 |
| calls.rb:319:1:319:6 | call to []= | []= | 2 | calls.rb:319:8:319:9 | __synth__2 |
| calls.rb:319:8:319:9 | ... + ... | + | 0 | calls.rb:319:11:319:11 | 1 |
| calls.rb:320:1:320:32 | ...[...] | [] | 0 | calls.rb:320:9:320:9 | 0 |
| calls.rb:320:1:320:32 | ...[...] | [] | 1 | calls.rb:320:12:320:18 | call to baz |
| calls.rb:320:1:320:32 | ...[...] | [] | 2 | calls.rb:320:21:320:31 | ... + ... |
| calls.rb:320:1:320:32 | call to [] | [] | 0 | calls.rb:320:9:320:9 | __synth__1 |
| calls.rb:320:1:320:32 | call to [] | [] | 1 | calls.rb:320:12:320:18 | __synth__2 |
| calls.rb:320:1:320:32 | call to [] | [] | 2 | calls.rb:320:21:320:31 | __synth__3 |
| calls.rb:320:1:320:32 | call to []= | []= | 0 | calls.rb:320:9:320:9 | __synth__1 |
| calls.rb:320:1:320:32 | call to []= | []= | 1 | calls.rb:320:12:320:18 | __synth__2 |
| calls.rb:320:1:320:32 | call to []= | []= | 2 | calls.rb:320:21:320:31 | __synth__3 |
| calls.rb:320:1:320:32 | call to []= | []= | 4 | calls.rb:320:34:320:35 | __synth__4 |
| calls.rb:320:21:320:31 | ... + ... | + | 0 | calls.rb:320:31:320:31 | 1 |
| calls.rb:320:34:320:35 | ... * ... | * | 0 | calls.rb:320:37:320:37 | 2 |
| calls.rb:328:25:328:37 | call to print | print | 0 | calls.rb:328:31:328:37 | "error" |
| calls.rb:332:3:332:12 | super call to foo | foo | 0 | calls.rb:332:9:332:11 | ... |
| calls.rb:336:3:336:13 | call to bar | bar | 0 | calls.rb:336:7:336:7 | b |
| calls.rb:336:3:336:13 | call to bar | bar | 1 | calls.rb:336:10:336:12 | ... |
| calls.rb:340:5:340:5 | call to [] | [] | 0 | calls.rb:340:5:340:5 | 0 |
| calls.rb:340:8:340:8 | call to [] | [] | 0 | calls.rb:340:8:340:8 | 1 |
| calls.rb:340:11:340:11 | call to [] | [] | 0 | calls.rb:340:11:340:11 | 2 |
| calls.rb:340:16:340:33 | call to [] | [] | 0 | calls.rb:340:17:340:23 | [...] |
| calls.rb:340:16:340:33 | call to [] | [] | 1 | calls.rb:340:26:340:32 | [...] |
| calls.rb:340:17:340:23 | call to [] | [] | 0 | calls.rb:340:18:340:18 | 1 |
| calls.rb:340:17:340:23 | call to [] | [] | 1 | calls.rb:340:20:340:20 | 2 |
| calls.rb:340:17:340:23 | call to [] | [] | 2 | calls.rb:340:22:340:22 | 3 |
| calls.rb:340:26:340:32 | call to [] | [] | 0 | calls.rb:340:27:340:27 | 4 |
| calls.rb:340:26:340:32 | call to [] | [] | 1 | calls.rb:340:29:340:29 | 5 |
| calls.rb:340:26:340:32 | call to [] | [] | 2 | calls.rb:340:31:340:31 | 6 |
| calls.rb:341:3:341:13 | call to foo | foo | 0 | calls.rb:341:7:341:7 | x |
| calls.rb:341:3:341:13 | call to foo | foo | 1 | calls.rb:341:10:341:10 | y |
| calls.rb:341:3:341:13 | call to foo | foo | 2 | calls.rb:341:13:341:13 | z |
| calls.rb:344:1:344:10 | call to foo | foo | 0 | calls.rb:344:5:344:9 | Pair |
| calls.rb:345:1:345:15 | call to foo | foo | 0 | calls.rb:345:5:345:6 | Pair |
| calls.rb:345:1:345:15 | call to foo | foo | 1 | calls.rb:345:9:345:14 | Pair |
| calls.rb:272:1:272:6 | call to foo | foo | 0 | calls.rb:272:5:272:5 | * ... |
| calls.rb:275:1:275:10 | call to foo | foo | 0 | calls.rb:275:5:275:9 | ** ... |
| calls.rb:276:1:276:13 | call to foo | foo | 0 | calls.rb:276:5:276:12 | ** ... |
| calls.rb:277:1:277:7 | call to foo | foo | 0 | calls.rb:277:5:277:6 | ** ... |
| calls.rb:280:1:280:14 | call to foo | foo | 0 | calls.rb:280:5:280:13 | Pair |
| calls.rb:281:1:281:17 | call to foo | foo | 0 | calls.rb:281:5:281:16 | Pair |
| calls.rb:290:5:290:16 | super call to my_method | my_method | 0 | calls.rb:290:11:290:16 | "blah" |
| calls.rb:291:5:291:17 | super call to my_method | my_method | 0 | calls.rb:291:11:291:11 | 1 |
| calls.rb:291:5:291:17 | super call to my_method | my_method | 1 | calls.rb:291:14:291:14 | 2 |
| calls.rb:291:5:291:17 | super call to my_method | my_method | 2 | calls.rb:291:17:291:17 | 3 |
| calls.rb:292:17:292:21 | ... + ... | + | 0 | calls.rb:292:21:292:21 | 1 |
| calls.rb:293:18:293:22 | ... * ... | * | 0 | calls.rb:293:22:293:22 | 2 |
| calls.rb:294:5:294:30 | super call to my_method | my_method | 0 | calls.rb:294:11:294:11 | 4 |
| calls.rb:294:5:294:30 | super call to my_method | my_method | 1 | calls.rb:294:14:294:14 | 5 |
| calls.rb:294:22:294:28 | ... + ... | + | 0 | calls.rb:294:26:294:28 | 100 |
| calls.rb:295:5:295:33 | super call to my_method | my_method | 0 | calls.rb:295:11:295:11 | 6 |
| calls.rb:295:5:295:33 | super call to my_method | my_method | 1 | calls.rb:295:14:295:14 | 7 |
| calls.rb:295:23:295:29 | ... + ... | + | 0 | calls.rb:295:27:295:29 | 200 |
| calls.rb:313:1:313:7 | call to call | call | 0 | calls.rb:313:6:313:6 | 1 |
| calls.rb:316:1:316:8 | call to foo= | foo= | 0 | calls.rb:316:12:316:13 | ... = ... |
| calls.rb:317:1:317:6 | ...[...] | [] | 0 | calls.rb:317:5:317:5 | 0 |
| calls.rb:317:1:317:6 | call to []= | []= | 0 | calls.rb:317:5:317:5 | 0 |
| calls.rb:317:1:317:6 | call to []= | []= | 1 | calls.rb:317:10:317:11 | ... = ... |
| calls.rb:318:1:318:8 | call to [] | [] | 0 | calls.rb:318:1:318:8 | 0 |
| calls.rb:318:1:318:8 | call to foo= | foo= | 0 | calls.rb:318:1:318:8 | ... = ... |
| calls.rb:318:12:318:19 | call to [] | [] | 0 | calls.rb:318:12:318:19 | _ .. _ |
| calls.rb:318:12:318:19 | call to bar= | bar= | 0 | calls.rb:318:12:318:19 | ... = ... |
| calls.rb:318:22:318:27 | ...[...] | [] | 0 | calls.rb:318:26:318:26 | 4 |
| calls.rb:318:22:318:27 | call to [] | [] | 0 | calls.rb:318:22:318:27 | -1 |
| calls.rb:318:22:318:27 | call to []= | []= | 0 | calls.rb:318:26:318:26 | 4 |
| calls.rb:318:22:318:27 | call to []= | []= | 1 | calls.rb:318:22:318:27 | ... = ... |
| calls.rb:318:31:318:42 | call to [] | [] | 0 | calls.rb:318:32:318:32 | 1 |
| calls.rb:318:31:318:42 | call to [] | [] | 1 | calls.rb:318:35:318:35 | 2 |
| calls.rb:318:31:318:42 | call to [] | [] | 2 | calls.rb:318:38:318:38 | 3 |
| calls.rb:318:31:318:42 | call to [] | [] | 3 | calls.rb:318:41:318:41 | 4 |
| calls.rb:319:1:319:1 | call to [] | [] | 0 | calls.rb:319:1:319:1 | 0 |
| calls.rb:319:5:319:10 | ...[...] | [] | 0 | calls.rb:319:9:319:9 | 5 |
| calls.rb:319:5:319:10 | call to [] | [] | 0 | calls.rb:319:5:319:10 | _ .. _ |
| calls.rb:319:5:319:10 | call to []= | []= | 0 | calls.rb:319:9:319:9 | 5 |
| calls.rb:319:5:319:10 | call to []= | []= | 1 | calls.rb:319:5:319:10 | ... = ... |
| calls.rb:319:14:319:22 | call to [] | [] | 0 | calls.rb:319:15:319:15 | 1 |
| calls.rb:319:14:319:22 | call to [] | [] | 1 | calls.rb:319:18:319:18 | 2 |
| calls.rb:319:14:319:22 | call to [] | [] | 2 | calls.rb:319:21:319:21 | 3 |
| calls.rb:320:1:320:10 | call to count= | count= | 1 | calls.rb:320:12:320:13 | __synth__1 |
| calls.rb:320:12:320:13 | ... + ... | + | 0 | calls.rb:320:15:320:15 | 1 |
| calls.rb:321:1:321:6 | ...[...] | [] | 0 | calls.rb:321:5:321:5 | 0 |
| calls.rb:321:1:321:6 | call to [] | [] | 0 | calls.rb:321:5:321:5 | __synth__1 |
| calls.rb:321:1:321:6 | call to []= | []= | 0 | calls.rb:321:5:321:5 | __synth__1 |
| calls.rb:321:1:321:6 | call to []= | []= | 2 | calls.rb:321:8:321:9 | __synth__2 |
| calls.rb:321:8:321:9 | ... + ... | + | 0 | calls.rb:321:11:321:11 | 1 |
| calls.rb:322:1:322:32 | ...[...] | [] | 0 | calls.rb:322:9:322:9 | 0 |
| calls.rb:322:1:322:32 | ...[...] | [] | 1 | calls.rb:322:12:322:18 | call to baz |
| calls.rb:322:1:322:32 | ...[...] | [] | 2 | calls.rb:322:21:322:31 | ... + ... |
| calls.rb:322:1:322:32 | call to [] | [] | 0 | calls.rb:322:9:322:9 | __synth__1 |
| calls.rb:322:1:322:32 | call to [] | [] | 1 | calls.rb:322:12:322:18 | __synth__2 |
| calls.rb:322:1:322:32 | call to [] | [] | 2 | calls.rb:322:21:322:31 | __synth__3 |
| calls.rb:322:1:322:32 | call to []= | []= | 0 | calls.rb:322:9:322:9 | __synth__1 |
| calls.rb:322:1:322:32 | call to []= | []= | 1 | calls.rb:322:12:322:18 | __synth__2 |
| calls.rb:322:1:322:32 | call to []= | []= | 2 | calls.rb:322:21:322:31 | __synth__3 |
| calls.rb:322:1:322:32 | call to []= | []= | 4 | calls.rb:322:34:322:35 | __synth__4 |
| calls.rb:322:21:322:31 | ... + ... | + | 0 | calls.rb:322:31:322:31 | 1 |
| calls.rb:322:34:322:35 | ... * ... | * | 0 | calls.rb:322:37:322:37 | 2 |
| calls.rb:330:25:330:37 | call to print | print | 0 | calls.rb:330:31:330:37 | "error" |
| calls.rb:334:3:334:12 | super call to foo | foo | 0 | calls.rb:334:9:334:11 | ... |
| calls.rb:338:3:338:13 | call to bar | bar | 0 | calls.rb:338:7:338:7 | b |
| calls.rb:338:3:338:13 | call to bar | bar | 1 | calls.rb:338:10:338:12 | ... |
| calls.rb:342:5:342:5 | call to [] | [] | 0 | calls.rb:342:5:342:5 | 0 |
| calls.rb:342:8:342:8 | call to [] | [] | 0 | calls.rb:342:8:342:8 | 1 |
| calls.rb:342:11:342:11 | call to [] | [] | 0 | calls.rb:342:11:342:11 | 2 |
| calls.rb:342:16:342:33 | call to [] | [] | 0 | calls.rb:342:17:342:23 | [...] |
| calls.rb:342:16:342:33 | call to [] | [] | 1 | calls.rb:342:26:342:32 | [...] |
| calls.rb:342:17:342:23 | call to [] | [] | 0 | calls.rb:342:18:342:18 | 1 |
| calls.rb:342:17:342:23 | call to [] | [] | 1 | calls.rb:342:20:342:20 | 2 |
| calls.rb:342:17:342:23 | call to [] | [] | 2 | calls.rb:342:22:342:22 | 3 |
| calls.rb:342:26:342:32 | call to [] | [] | 0 | calls.rb:342:27:342:27 | 4 |
| calls.rb:342:26:342:32 | call to [] | [] | 1 | calls.rb:342:29:342:29 | 5 |
| calls.rb:342:26:342:32 | call to [] | [] | 2 | calls.rb:342:31:342:31 | 6 |
| calls.rb:343:3:343:13 | call to foo | foo | 0 | calls.rb:343:7:343:7 | x |
| calls.rb:343:3:343:13 | call to foo | foo | 1 | calls.rb:343:10:343:10 | y |
| calls.rb:343:3:343:13 | call to foo | foo | 2 | calls.rb:343:13:343:13 | z |
| calls.rb:346:1:346:10 | call to foo | foo | 0 | calls.rb:346:5:346:9 | Pair |
| calls.rb:347:1:347:7 | call to foo | foo | 0 | calls.rb:347:5:347:6 | Pair |
| calls.rb:352:13:352:17 | call to foo | foo | 0 | calls.rb:352:17:352:17 | x |
| calls.rb:362:5:362:6 | call to == | == | 0 | calls.rb:362:1:362:4 | __synth__0__1 |
| calls.rb:364:1:364:23 | call to bar | bar | 0 | calls.rb:364:10:364:10 | 1 |
| calls.rb:364:1:364:23 | call to bar | bar | 0 | calls.rb:364:10:364:10 | 1 |
| calls.rb:364:1:364:23 | call to bar | bar | 1 | calls.rb:364:12:364:12 | 2 |
| calls.rb:364:1:364:23 | call to bar | bar | 1 | calls.rb:364:12:364:12 | 2 |
| calls.rb:364:4:364:5 | call to == | == | 0 | calls.rb:364:1:364:3 | __synth__0__1 |
| calls.rb:347:1:347:15 | call to foo | foo | 0 | calls.rb:347:5:347:6 | Pair |
| calls.rb:347:1:347:15 | call to foo | foo | 1 | calls.rb:347:9:347:14 | Pair |
| calls.rb:348:1:348:10 | call to foo | foo | 0 | calls.rb:348:5:348:9 | Pair |
| calls.rb:349:1:349:7 | call to foo | foo | 0 | calls.rb:349:5:349:6 | Pair |
| calls.rb:354:13:354:17 | call to foo | foo | 0 | calls.rb:354:17:354:17 | x |
| calls.rb:364:5:364:6 | call to == | == | 0 | calls.rb:364:1:364:4 | __synth__0__1 |
| calls.rb:366:1:366:23 | call to bar | bar | 0 | calls.rb:366:10:366:10 | 1 |
| calls.rb:366:1:366:23 | call to bar | bar | 0 | calls.rb:366:10:366:10 | 1 |
| calls.rb:366:1:366:23 | call to bar | bar | 1 | calls.rb:366:12:366:12 | 2 |
| calls.rb:366:1:366:23 | call to bar | bar | 1 | calls.rb:366:12:366:12 | 2 |
| calls.rb:366:4:366:5 | call to == | == | 0 | calls.rb:366:1:366:3 | __synth__0__1 |
callsWithReceiver
| calls.rb:2:1:2:5 | call to foo | calls.rb:2:1:2:5 | self |
| calls.rb:5:1:5:10 | call to bar | calls.rb:5:1:5:3 | Foo |
@@ -288,108 +292,110 @@ callsWithReceiver
| calls.rb:271:1:271:12 | call to foo | calls.rb:271:1:271:12 | self |
| calls.rb:271:5:271:11 | * ... | calls.rb:271:6:271:11 | call to bar |
| calls.rb:271:6:271:11 | call to bar | calls.rb:271:6:271:6 | X |
| calls.rb:274:1:274:10 | call to foo | calls.rb:274:1:274:10 | self |
| calls.rb:274:5:274:9 | ** ... | calls.rb:274:7:274:9 | call to bar |
| calls.rb:274:7:274:9 | call to bar | calls.rb:274:7:274:9 | self |
| calls.rb:275:1:275:13 | call to foo | calls.rb:275:1:275:13 | self |
| calls.rb:275:5:275:12 | ** ... | calls.rb:275:7:275:12 | call to bar |
| calls.rb:275:7:275:12 | call to bar | calls.rb:275:7:275:7 | X |
| calls.rb:278:1:278:14 | call to foo | calls.rb:278:1:278:14 | self |
| calls.rb:278:11:278:13 | call to bar | calls.rb:278:11:278:13 | self |
| calls.rb:279:1:279:17 | call to foo | calls.rb:279:1:279:17 | self |
| calls.rb:279:11:279:16 | call to bar | calls.rb:279:11:279:11 | X |
| calls.rb:290:17:290:21 | ... + ... | calls.rb:290:17:290:17 | x |
| calls.rb:291:18:291:22 | ... * ... | calls.rb:291:18:291:18 | x |
| calls.rb:292:22:292:28 | ... + ... | calls.rb:292:22:292:22 | x |
| calls.rb:293:23:293:29 | ... + ... | calls.rb:293:23:293:23 | x |
| calls.rb:303:5:303:7 | call to foo | calls.rb:303:5:303:7 | self |
| calls.rb:303:5:303:13 | call to super | calls.rb:303:5:303:7 | call to foo |
| calls.rb:304:5:304:14 | call to super | calls.rb:304:5:304:8 | self |
| calls.rb:305:5:305:15 | call to super | calls.rb:305:5:305:9 | super call to another_method |
| calls.rb:310:1:310:3 | call to foo | calls.rb:310:1:310:3 | self |
| calls.rb:310:1:310:6 | call to call | calls.rb:310:1:310:3 | call to foo |
| calls.rb:311:1:311:3 | call to foo | calls.rb:311:1:311:3 | self |
| calls.rb:311:1:311:7 | call to call | calls.rb:311:1:311:3 | call to foo |
| calls.rb:314:1:314:8 | call to foo | calls.rb:314:1:314:4 | self |
| calls.rb:314:1:314:8 | call to foo= | calls.rb:314:1:314:4 | self |
| calls.rb:315:1:315:3 | call to foo | calls.rb:315:1:315:3 | self |
| calls.rb:315:1:315:6 | ...[...] | calls.rb:315:1:315:3 | call to foo |
| calls.rb:315:1:315:6 | call to []= | calls.rb:315:1:315:3 | call to foo |
| calls.rb:316:1:316:8 | call to [] | calls.rb:316:1:316:8 | __synth__0 |
| calls.rb:272:1:272:6 | call to foo | calls.rb:272:1:272:6 | self |
| calls.rb:275:1:275:10 | call to foo | calls.rb:275:1:275:10 | self |
| calls.rb:275:5:275:9 | ** ... | calls.rb:275:7:275:9 | call to bar |
| calls.rb:275:7:275:9 | call to bar | calls.rb:275:7:275:9 | self |
| calls.rb:276:1:276:13 | call to foo | calls.rb:276:1:276:13 | self |
| calls.rb:276:5:276:12 | ** ... | calls.rb:276:7:276:12 | call to bar |
| calls.rb:276:7:276:12 | call to bar | calls.rb:276:7:276:7 | X |
| calls.rb:277:1:277:7 | call to foo | calls.rb:277:1:277:7 | self |
| calls.rb:280:1:280:14 | call to foo | calls.rb:280:1:280:14 | self |
| calls.rb:280:11:280:13 | call to bar | calls.rb:280:11:280:13 | self |
| calls.rb:281:1:281:17 | call to foo | calls.rb:281:1:281:17 | self |
| calls.rb:281:11:281:16 | call to bar | calls.rb:281:11:281:11 | X |
| calls.rb:292:17:292:21 | ... + ... | calls.rb:292:17:292:17 | x |
| calls.rb:293:18:293:22 | ... * ... | calls.rb:293:18:293:18 | x |
| calls.rb:294:22:294:28 | ... + ... | calls.rb:294:22:294:22 | x |
| calls.rb:295:23:295:29 | ... + ... | calls.rb:295:23:295:23 | x |
| calls.rb:305:5:305:7 | call to foo | calls.rb:305:5:305:7 | self |
| calls.rb:305:5:305:13 | call to super | calls.rb:305:5:305:7 | call to foo |
| calls.rb:306:5:306:14 | call to super | calls.rb:306:5:306:8 | self |
| calls.rb:307:5:307:15 | call to super | calls.rb:307:5:307:9 | super call to another_method |
| calls.rb:312:1:312:3 | call to foo | calls.rb:312:1:312:3 | self |
| calls.rb:312:1:312:6 | call to call | calls.rb:312:1:312:3 | call to foo |
| calls.rb:313:1:313:3 | call to foo | calls.rb:313:1:313:3 | self |
| calls.rb:313:1:313:7 | call to call | calls.rb:313:1:313:3 | call to foo |
| calls.rb:316:1:316:8 | call to foo | calls.rb:316:1:316:4 | self |
| calls.rb:316:1:316:8 | call to foo= | calls.rb:316:1:316:4 | self |
| calls.rb:316:12:316:19 | call to [] | calls.rb:316:12:316:19 | __synth__0 |
| calls.rb:316:12:316:19 | call to bar | calls.rb:316:12:316:15 | self |
| calls.rb:316:12:316:19 | call to bar= | calls.rb:316:12:316:15 | self |
| calls.rb:316:22:316:24 | call to foo | calls.rb:316:22:316:24 | self |
| calls.rb:316:22:316:27 | ...[...] | calls.rb:316:22:316:24 | call to foo |
| calls.rb:316:22:316:27 | call to [] | calls.rb:316:22:316:27 | __synth__0 |
| calls.rb:316:22:316:27 | call to []= | calls.rb:316:22:316:24 | call to foo |
| calls.rb:316:31:316:42 | * ... | calls.rb:316:31:316:42 | [...] |
| calls.rb:316:31:316:42 | call to [] | calls.rb:316:31:316:42 | Array |
| calls.rb:317:1:317:1 | call to [] | calls.rb:317:1:317:1 | __synth__0 |
| calls.rb:317:5:317:7 | call to foo | calls.rb:317:5:317:7 | self |
| calls.rb:317:5:317:10 | ...[...] | calls.rb:317:5:317:7 | call to foo |
| calls.rb:317:5:317:10 | call to [] | calls.rb:317:5:317:10 | __synth__0 |
| calls.rb:317:5:317:10 | call to []= | calls.rb:317:5:317:7 | call to foo |
| calls.rb:317:14:317:22 | * ... | calls.rb:317:14:317:22 | [...] |
| calls.rb:317:14:317:22 | call to [] | calls.rb:317:14:317:22 | Array |
| calls.rb:318:1:318:10 | call to count | calls.rb:318:1:318:4 | __synth__0 |
| calls.rb:318:1:318:10 | call to count | calls.rb:318:1:318:4 | self |
| calls.rb:318:1:318:10 | call to count= | calls.rb:318:1:318:4 | __synth__0 |
| calls.rb:318:12:318:13 | ... + ... | calls.rb:318:1:318:10 | call to count |
| calls.rb:319:1:319:3 | call to foo | calls.rb:319:1:319:3 | self |
| calls.rb:319:1:319:6 | ...[...] | calls.rb:319:1:319:3 | call to foo |
| calls.rb:319:1:319:6 | call to [] | calls.rb:319:1:319:3 | __synth__0 |
| calls.rb:319:1:319:6 | call to []= | calls.rb:319:1:319:3 | __synth__0 |
| calls.rb:319:8:319:9 | ... + ... | calls.rb:319:1:319:6 | call to [] |
| calls.rb:320:1:320:3 | call to foo | calls.rb:320:1:320:3 | self |
| calls.rb:320:1:320:7 | call to bar | calls.rb:320:1:320:3 | call to foo |
| calls.rb:320:1:320:32 | ...[...] | calls.rb:320:1:320:7 | call to bar |
| calls.rb:320:1:320:32 | call to [] | calls.rb:320:1:320:7 | __synth__0 |
| calls.rb:320:1:320:32 | call to []= | calls.rb:320:1:320:7 | __synth__0 |
| calls.rb:320:12:320:14 | call to foo | calls.rb:320:12:320:14 | self |
| calls.rb:320:12:320:18 | call to baz | calls.rb:320:12:320:14 | call to foo |
| calls.rb:320:21:320:23 | call to foo | calls.rb:320:21:320:23 | self |
| calls.rb:320:21:320:27 | call to boo | calls.rb:320:21:320:23 | call to foo |
| calls.rb:320:21:320:31 | ... + ... | calls.rb:320:21:320:27 | call to boo |
| calls.rb:320:34:320:35 | ... * ... | calls.rb:320:1:320:32 | call to [] |
| calls.rb:323:11:323:13 | call to bar | calls.rb:323:11:323:13 | self |
| calls.rb:324:13:324:15 | call to bar | calls.rb:324:13:324:15 | self |
| calls.rb:325:14:325:16 | call to bar | calls.rb:325:14:325:16 | self |
| calls.rb:326:18:326:20 | call to bar | calls.rb:326:18:326:20 | self |
| calls.rb:327:22:327:24 | call to bar | calls.rb:327:22:327:24 | self |
| calls.rb:328:13:328:15 | call to bar | calls.rb:328:13:328:15 | self |
| calls.rb:328:25:328:37 | call to print | calls.rb:328:25:328:37 | self |
| calls.rb:336:3:336:13 | call to bar | calls.rb:336:3:336:13 | self |
| calls.rb:340:1:342:3 | * ... | calls.rb:340:1:342:3 | __synth__0__1 |
| calls.rb:340:1:342:3 | call to each | calls.rb:340:16:340:33 | [...] |
| calls.rb:340:5:340:5 | call to [] | calls.rb:340:5:340:5 | __synth__0__1 |
| calls.rb:340:8:340:8 | call to [] | calls.rb:340:8:340:8 | __synth__0__1 |
| calls.rb:340:11:340:11 | call to [] | calls.rb:340:11:340:11 | __synth__0__1 |
| calls.rb:340:16:340:33 | call to [] | calls.rb:340:16:340:33 | Array |
| calls.rb:340:17:340:23 | call to [] | calls.rb:340:17:340:23 | Array |
| calls.rb:340:26:340:32 | call to [] | calls.rb:340:26:340:32 | Array |
| calls.rb:341:3:341:13 | call to foo | calls.rb:341:3:341:13 | self |
| calls.rb:344:1:344:10 | call to foo | calls.rb:344:1:344:10 | self |
| calls.rb:345:1:345:15 | call to foo | calls.rb:345:1:345:15 | self |
| calls.rb:317:1:317:3 | call to foo | calls.rb:317:1:317:3 | self |
| calls.rb:317:1:317:6 | ...[...] | calls.rb:317:1:317:3 | call to foo |
| calls.rb:317:1:317:6 | call to []= | calls.rb:317:1:317:3 | call to foo |
| calls.rb:318:1:318:8 | call to [] | calls.rb:318:1:318:8 | __synth__0 |
| calls.rb:318:1:318:8 | call to foo | calls.rb:318:1:318:4 | self |
| calls.rb:318:1:318:8 | call to foo= | calls.rb:318:1:318:4 | self |
| calls.rb:318:12:318:19 | call to [] | calls.rb:318:12:318:19 | __synth__0 |
| calls.rb:318:12:318:19 | call to bar | calls.rb:318:12:318:15 | self |
| calls.rb:318:12:318:19 | call to bar= | calls.rb:318:12:318:15 | self |
| calls.rb:318:22:318:24 | call to foo | calls.rb:318:22:318:24 | self |
| calls.rb:318:22:318:27 | ...[...] | calls.rb:318:22:318:24 | call to foo |
| calls.rb:318:22:318:27 | call to [] | calls.rb:318:22:318:27 | __synth__0 |
| calls.rb:318:22:318:27 | call to []= | calls.rb:318:22:318:24 | call to foo |
| calls.rb:318:31:318:42 | * ... | calls.rb:318:31:318:42 | [...] |
| calls.rb:318:31:318:42 | call to [] | calls.rb:318:31:318:42 | Array |
| calls.rb:319:1:319:1 | call to [] | calls.rb:319:1:319:1 | __synth__0 |
| calls.rb:319:5:319:7 | call to foo | calls.rb:319:5:319:7 | self |
| calls.rb:319:5:319:10 | ...[...] | calls.rb:319:5:319:7 | call to foo |
| calls.rb:319:5:319:10 | call to [] | calls.rb:319:5:319:10 | __synth__0 |
| calls.rb:319:5:319:10 | call to []= | calls.rb:319:5:319:7 | call to foo |
| calls.rb:319:14:319:22 | * ... | calls.rb:319:14:319:22 | [...] |
| calls.rb:319:14:319:22 | call to [] | calls.rb:319:14:319:22 | Array |
| calls.rb:320:1:320:10 | call to count | calls.rb:320:1:320:4 | __synth__0 |
| calls.rb:320:1:320:10 | call to count | calls.rb:320:1:320:4 | self |
| calls.rb:320:1:320:10 | call to count= | calls.rb:320:1:320:4 | __synth__0 |
| calls.rb:320:12:320:13 | ... + ... | calls.rb:320:1:320:10 | call to count |
| calls.rb:321:1:321:3 | call to foo | calls.rb:321:1:321:3 | self |
| calls.rb:321:1:321:6 | ...[...] | calls.rb:321:1:321:3 | call to foo |
| calls.rb:321:1:321:6 | call to [] | calls.rb:321:1:321:3 | __synth__0 |
| calls.rb:321:1:321:6 | call to []= | calls.rb:321:1:321:3 | __synth__0 |
| calls.rb:321:8:321:9 | ... + ... | calls.rb:321:1:321:6 | call to [] |
| calls.rb:322:1:322:3 | call to foo | calls.rb:322:1:322:3 | self |
| calls.rb:322:1:322:7 | call to bar | calls.rb:322:1:322:3 | call to foo |
| calls.rb:322:1:322:32 | ...[...] | calls.rb:322:1:322:7 | call to bar |
| calls.rb:322:1:322:32 | call to [] | calls.rb:322:1:322:7 | __synth__0 |
| calls.rb:322:1:322:32 | call to []= | calls.rb:322:1:322:7 | __synth__0 |
| calls.rb:322:12:322:14 | call to foo | calls.rb:322:12:322:14 | self |
| calls.rb:322:12:322:18 | call to baz | calls.rb:322:12:322:14 | call to foo |
| calls.rb:322:21:322:23 | call to foo | calls.rb:322:21:322:23 | self |
| calls.rb:322:21:322:27 | call to boo | calls.rb:322:21:322:23 | call to foo |
| calls.rb:322:21:322:31 | ... + ... | calls.rb:322:21:322:27 | call to boo |
| calls.rb:322:34:322:35 | ... * ... | calls.rb:322:1:322:32 | call to [] |
| calls.rb:325:11:325:13 | call to bar | calls.rb:325:11:325:13 | self |
| calls.rb:326:13:326:15 | call to bar | calls.rb:326:13:326:15 | self |
| calls.rb:327:14:327:16 | call to bar | calls.rb:327:14:327:16 | self |
| calls.rb:328:18:328:20 | call to bar | calls.rb:328:18:328:20 | self |
| calls.rb:329:22:329:24 | call to bar | calls.rb:329:22:329:24 | self |
| calls.rb:330:13:330:15 | call to bar | calls.rb:330:13:330:15 | self |
| calls.rb:330:25:330:37 | call to print | calls.rb:330:25:330:37 | self |
| calls.rb:338:3:338:13 | call to bar | calls.rb:338:3:338:13 | self |
| calls.rb:342:1:344:3 | * ... | calls.rb:342:1:344:3 | __synth__0__1 |
| calls.rb:342:1:344:3 | call to each | calls.rb:342:16:342:33 | [...] |
| calls.rb:342:5:342:5 | call to [] | calls.rb:342:5:342:5 | __synth__0__1 |
| calls.rb:342:8:342:8 | call to [] | calls.rb:342:8:342:8 | __synth__0__1 |
| calls.rb:342:11:342:11 | call to [] | calls.rb:342:11:342:11 | __synth__0__1 |
| calls.rb:342:16:342:33 | call to [] | calls.rb:342:16:342:33 | Array |
| calls.rb:342:17:342:23 | call to [] | calls.rb:342:17:342:23 | Array |
| calls.rb:342:26:342:32 | call to [] | calls.rb:342:26:342:32 | Array |
| calls.rb:343:3:343:13 | call to foo | calls.rb:343:3:343:13 | self |
| calls.rb:346:1:346:10 | call to foo | calls.rb:346:1:346:10 | self |
| calls.rb:347:1:347:7 | call to foo | calls.rb:347:1:347:7 | self |
| calls.rb:352:13:352:17 | call to foo | calls.rb:352:13:352:17 | self |
| calls.rb:353:13:353:24 | call to unknown_call | calls.rb:353:13:353:24 | self |
| calls.rb:357:3:357:14 | call to unknown_call | calls.rb:357:3:357:14 | self |
| calls.rb:361:1:361:4 | call to list | calls.rb:361:1:361:4 | self |
| calls.rb:361:1:361:11 | call to empty? | calls.rb:361:1:361:4 | call to list |
| calls.rb:362:1:362:4 | call to list | calls.rb:362:1:362:4 | self |
| calls.rb:362:1:362:12 | call to empty? | calls.rb:362:1:362:4 | __synth__0__1 |
| calls.rb:362:1:362:12 | call to empty? | calls.rb:362:1:362:4 | call to list |
| calls.rb:362:5:362:6 | call to == | calls.rb:362:5:362:6 | nil |
| calls.rb:347:1:347:15 | call to foo | calls.rb:347:1:347:15 | self |
| calls.rb:348:1:348:10 | call to foo | calls.rb:348:1:348:10 | self |
| calls.rb:349:1:349:7 | call to foo | calls.rb:349:1:349:7 | self |
| calls.rb:354:13:354:17 | call to foo | calls.rb:354:13:354:17 | self |
| calls.rb:355:13:355:24 | call to unknown_call | calls.rb:355:13:355:24 | self |
| calls.rb:359:3:359:14 | call to unknown_call | calls.rb:359:3:359:14 | self |
| calls.rb:363:1:363:4 | call to list | calls.rb:363:1:363:4 | self |
| calls.rb:363:1:363:12 | call to empty? | calls.rb:363:1:363:4 | call to list |
| calls.rb:364:1:364:3 | call to foo | calls.rb:364:1:364:3 | self |
| calls.rb:364:1:364:23 | call to bar | calls.rb:364:1:364:3 | __synth__0__1 |
| calls.rb:364:1:364:23 | call to bar | calls.rb:364:1:364:3 | call to foo |
| calls.rb:364:4:364:5 | call to == | calls.rb:364:4:364:5 | nil |
| calls.rb:363:1:363:11 | call to empty? | calls.rb:363:1:363:4 | call to list |
| calls.rb:364:1:364:4 | call to list | calls.rb:364:1:364:4 | self |
| calls.rb:364:1:364:12 | call to empty? | calls.rb:364:1:364:4 | __synth__0__1 |
| calls.rb:364:1:364:12 | call to empty? | calls.rb:364:1:364:4 | call to list |
| calls.rb:364:5:364:6 | call to == | calls.rb:364:5:364:6 | nil |
| calls.rb:365:1:365:4 | call to list | calls.rb:365:1:365:4 | self |
| calls.rb:365:1:365:12 | call to empty? | calls.rb:365:1:365:4 | call to list |
| calls.rb:366:1:366:3 | call to foo | calls.rb:366:1:366:3 | self |
| calls.rb:366:1:366:23 | call to bar | calls.rb:366:1:366:3 | __synth__0__1 |
| calls.rb:366:1:366:23 | call to bar | calls.rb:366:1:366:3 | call to foo |
| calls.rb:366:4:366:5 | call to == | calls.rb:366:4:366:5 | nil |
callsWithBlock
| calls.rb:17:1:17:17 | call to foo | calls.rb:17:5:17:17 | { ... } |
| calls.rb:20:1:22:3 | call to foo | calls.rb:20:5:22:3 | do ... end |
@@ -398,52 +404,52 @@ callsWithBlock
| calls.rb:95:1:98:3 | call to foo | calls.rb:95:7:98:3 | do ... end |
| calls.rb:226:1:228:3 | call to each | calls.rb:226:1:228:3 | { ... } |
| calls.rb:229:1:231:3 | call to each | calls.rb:229:1:231:3 | { ... } |
| calls.rb:290:5:290:23 | super call to my_method | calls.rb:290:11:290:23 | { ... } |
| calls.rb:291:5:291:26 | super call to my_method | calls.rb:291:11:291:26 | do ... end |
| calls.rb:292:5:292:30 | super call to my_method | calls.rb:292:16:292:30 | { ... } |
| calls.rb:293:5:293:33 | super call to my_method | calls.rb:293:16:293:33 | do ... end |
| calls.rb:340:1:342:3 | call to each | calls.rb:340:1:342:3 | { ... } |
| calls.rb:364:1:364:23 | call to bar | calls.rb:364:15:364:23 | { ... } |
| calls.rb:364:1:364:23 | call to bar | calls.rb:364:15:364:23 | { ... } |
| calls.rb:292:5:292:23 | super call to my_method | calls.rb:292:11:292:23 | { ... } |
| calls.rb:293:5:293:26 | super call to my_method | calls.rb:293:11:293:26 | do ... end |
| calls.rb:294:5:294:30 | super call to my_method | calls.rb:294:16:294:30 | { ... } |
| calls.rb:295:5:295:33 | super call to my_method | calls.rb:295:16:295:33 | do ... end |
| calls.rb:342:1:344:3 | call to each | calls.rb:342:1:344:3 | { ... } |
| calls.rb:366:1:366:23 | call to bar | calls.rb:366:15:366:23 | { ... } |
| calls.rb:366:1:366:23 | call to bar | calls.rb:366:15:366:23 | { ... } |
yieldCalls
| calls.rb:31:3:31:7 | yield ... |
| calls.rb:36:3:36:16 | yield ... |
superCalls
| calls.rb:286:5:286:9 | super call to my_method |
| calls.rb:287:5:287:11 | super call to my_method |
| calls.rb:288:5:288:16 | super call to my_method |
| calls.rb:289:5:289:17 | super call to my_method |
| calls.rb:290:5:290:23 | super call to my_method |
| calls.rb:291:5:291:26 | super call to my_method |
| calls.rb:292:5:292:30 | super call to my_method |
| calls.rb:293:5:293:33 | super call to my_method |
| calls.rb:305:5:305:9 | super call to another_method |
| calls.rb:332:3:332:12 | super call to foo |
| calls.rb:288:5:288:9 | super call to my_method |
| calls.rb:289:5:289:11 | super call to my_method |
| calls.rb:290:5:290:16 | super call to my_method |
| calls.rb:291:5:291:17 | super call to my_method |
| calls.rb:292:5:292:23 | super call to my_method |
| calls.rb:293:5:293:26 | super call to my_method |
| calls.rb:294:5:294:30 | super call to my_method |
| calls.rb:295:5:295:33 | super call to my_method |
| calls.rb:307:5:307:9 | super call to another_method |
| calls.rb:334:3:334:12 | super call to foo |
superCallsWithArguments
| calls.rb:288:5:288:16 | super call to my_method | 0 | calls.rb:288:11:288:16 | "blah" |
| calls.rb:289:5:289:17 | super call to my_method | 0 | calls.rb:289:11:289:11 | 1 |
| calls.rb:289:5:289:17 | super call to my_method | 1 | calls.rb:289:14:289:14 | 2 |
| calls.rb:289:5:289:17 | super call to my_method | 2 | calls.rb:289:17:289:17 | 3 |
| calls.rb:292:5:292:30 | super call to my_method | 0 | calls.rb:292:11:292:11 | 4 |
| calls.rb:292:5:292:30 | super call to my_method | 1 | calls.rb:292:14:292:14 | 5 |
| calls.rb:293:5:293:33 | super call to my_method | 0 | calls.rb:293:11:293:11 | 6 |
| calls.rb:293:5:293:33 | super call to my_method | 1 | calls.rb:293:14:293:14 | 7 |
| calls.rb:332:3:332:12 | super call to foo | 0 | calls.rb:332:9:332:11 | ... |
| calls.rb:290:5:290:16 | super call to my_method | 0 | calls.rb:290:11:290:16 | "blah" |
| calls.rb:291:5:291:17 | super call to my_method | 0 | calls.rb:291:11:291:11 | 1 |
| calls.rb:291:5:291:17 | super call to my_method | 1 | calls.rb:291:14:291:14 | 2 |
| calls.rb:291:5:291:17 | super call to my_method | 2 | calls.rb:291:17:291:17 | 3 |
| calls.rb:294:5:294:30 | super call to my_method | 0 | calls.rb:294:11:294:11 | 4 |
| calls.rb:294:5:294:30 | super call to my_method | 1 | calls.rb:294:14:294:14 | 5 |
| calls.rb:295:5:295:33 | super call to my_method | 0 | calls.rb:295:11:295:11 | 6 |
| calls.rb:295:5:295:33 | super call to my_method | 1 | calls.rb:295:14:295:14 | 7 |
| calls.rb:334:3:334:12 | super call to foo | 0 | calls.rb:334:9:334:11 | ... |
superCallsWithBlock
| calls.rb:290:5:290:23 | super call to my_method | calls.rb:290:11:290:23 | { ... } |
| calls.rb:291:5:291:26 | super call to my_method | calls.rb:291:11:291:26 | do ... end |
| calls.rb:292:5:292:30 | super call to my_method | calls.rb:292:16:292:30 | { ... } |
| calls.rb:293:5:293:33 | super call to my_method | calls.rb:293:16:293:33 | do ... end |
| calls.rb:292:5:292:23 | super call to my_method | calls.rb:292:11:292:23 | { ... } |
| calls.rb:293:5:293:26 | super call to my_method | calls.rb:293:11:293:26 | do ... end |
| calls.rb:294:5:294:30 | super call to my_method | calls.rb:294:16:294:30 | { ... } |
| calls.rb:295:5:295:33 | super call to my_method | calls.rb:295:16:295:33 | do ... end |
setterCalls
| calls.rb:314:1:314:8 | call to foo= |
| calls.rb:315:1:315:6 | call to []= |
| calls.rb:316:1:316:8 | call to foo= |
| calls.rb:316:12:316:19 | call to bar= |
| calls.rb:316:22:316:27 | call to []= |
| calls.rb:317:5:317:10 | call to []= |
| calls.rb:318:1:318:10 | call to count= |
| calls.rb:319:1:319:6 | call to []= |
| calls.rb:320:1:320:32 | call to []= |
| calls.rb:317:1:317:6 | call to []= |
| calls.rb:318:1:318:8 | call to foo= |
| calls.rb:318:12:318:19 | call to bar= |
| calls.rb:318:22:318:27 | call to []= |
| calls.rb:319:5:319:10 | call to []= |
| calls.rb:320:1:320:10 | call to count= |
| calls.rb:321:1:321:6 | call to []= |
| calls.rb:322:1:322:32 | call to []= |
callsWithSafeNavigationOperator
| calls.rb:362:1:362:12 | call to empty? |
| calls.rb:364:1:364:23 | call to bar |
| calls.rb:364:1:364:12 | call to empty? |
| calls.rb:366:1:366:23 | call to bar |

View File

@@ -269,10 +269,12 @@ foo(&)
# splat argument
foo(*bar)
foo(*X::bar)
foo(*)
# hash-splat argument
foo(**bar)
foo(**X::bar)
foo(**)
# the value in a keyword argument
foo(blah: bar)

View File

@@ -37,6 +37,8 @@ idParams
| params.rb:77:16:77:18 | val | val |
| params.rb:81:31:81:35 | array | array |
| params.rb:86:14:86:14 | x | x |
| params.rb:89:31:89:35 | array | array |
| params.rb:94:36:94:39 | hash | hash |
blockParams
| params.rb:46:28:46:33 | &block | block |
| params.rb:62:29:62:34 | &block | block |
@@ -91,6 +93,10 @@ paramsInMethods
| params.rb:73:1:74:3 | method_with_nil_splat | 1 | params.rb:73:35:73:39 | **nil | HashSplatNilParameter |
| params.rb:81:1:84:3 | anonymous_block_parameter | 0 | params.rb:81:31:81:35 | array | SimpleParameter |
| params.rb:81:1:84:3 | anonymous_block_parameter | 1 | params.rb:81:38:81:38 | & | BlockParameter |
| params.rb:89:1:91:3 | anonymous_splat_parameter | 0 | params.rb:89:31:89:35 | array | SimpleParameter |
| params.rb:89:1:91:3 | anonymous_splat_parameter | 1 | params.rb:89:38:89:38 | * | SplatParameter |
| params.rb:94:1:96:3 | anonymous_hash_splat_parameter | 0 | params.rb:94:36:94:39 | hash | SimpleParameter |
| params.rb:94:1:96:3 | anonymous_hash_splat_parameter | 1 | params.rb:94:42:94:43 | ** | HashSplatParameter |
paramsInBlocks
| params.rb:9:11:11:3 | do ... end | 0 | params.rb:9:15:9:17 | key | SimpleParameter |
| params.rb:9:11:11:3 | do ... end | 1 | params.rb:9:20:9:24 | value | SimpleParameter |
@@ -165,3 +171,7 @@ params
| params.rb:81:31:81:35 | array | 0 | SimpleParameter |
| params.rb:81:38:81:38 | & | 1 | BlockParameter |
| params.rb:86:14:86:14 | x | 0 | SimpleParameter |
| params.rb:89:31:89:35 | array | 0 | SimpleParameter |
| params.rb:89:38:89:38 | * | 1 | SplatParameter |
| params.rb:94:36:94:39 | hash | 0 | SimpleParameter |
| params.rb:94:42:94:43 | ** | 1 | HashSplatParameter |

View File

@@ -84,3 +84,13 @@ def anonymous_block_parameter(array, &)
end
run_block { |x; y, z | puts x }
# Anonymous splat parameter
def anonymous_splat_parameter(array, *)
array.concat(*)
end
# Anonymous hash splat parameter
def anonymous_hash_splat_parameter(hash, **)
hash.merge(**)
end

View File

@@ -3737,12 +3737,12 @@ cfg.rb:
#-----| -> exit do ... end
# 208| elem
#-----| -> *
#-----| -> __synth__0
# 208| *
#-----| -> **
# 208| __synth__0
#-----| -> __synth__0
# 208| **
# 208| __synth__0
#-----| -> elem
# 209| elem

View File

@@ -38,7 +38,7 @@ class ApiUseTest extends InlineExpectationsTest {
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "use" and // def tags are always optional
exists(API::Node a, DataFlow::Node n | relevantNode(a, n, location, tag) |
exists(DataFlow::Node n | relevantNode(_, n, location, tag) |
// Only report the longest path on this line:
value =
max(API::Node a2, Location l2, DataFlow::Node n2 |

View File

@@ -0,0 +1,4 @@
| rack.rb:1:1:5:3 | HelloWorld | rack.rb:2:12:2:14 | env |
| rack.rb:7:1:16:3 | Proxy | rack.rb:12:12:12:18 | the_env |
| rack.rb:18:1:31:3 | Logger | rack.rb:24:12:24:14 | env |
| rack.rb:45:1:61:3 | Baz | rack.rb:46:12:46:14 | env |

View File

@@ -0,0 +1,4 @@
private import codeql.ruby.frameworks.Rack
private import codeql.ruby.DataFlow
query predicate rackApps(Rack::AppCandidate c, DataFlow::ParameterNode env) { env = c.getEnv() }

View File

@@ -0,0 +1,61 @@
class HelloWorld
def call(env)
[200, {'Content-Type' => 'text/plain'}, ['Hello World']]
end
end
class Proxy
def initialize(app)
@app = app
end
def call(the_env)
status, headers, body = @app.call(the_env)
[status, headers, body]
end
end
class Logger
def initialize(app, logger = nil)
@app = app
@logger = logger
end
def call(env)
began_at = Utils.clock_time
status, header, body = @app.call(env)
header = Utils::HeaderHash.new(header)
body = BodyProxy.new(body) { log(env, status, header, began_at) }
[status, header, body]
end
end
class Foo
def not_call(env)
[1, 2, 3]
end
end
class Bar
def call(env)
nil
end
end
class Baz
def call(env)
run(env)
end
def run(env)
if env[:foo] == "foo"
[200, {}, "foo"]
else
error
end
end
def error
[400, {}, "nope"]
end
end

View File

@@ -1,4 +1,3 @@
| src/not_ruby.rb:5:25:5:26 | parse error | Extraction failed in src/not_ruby.rb with error parse error | 2 |
| src/unsupported_feature.rb:2:1:2:4 | parse error | Extraction failed in src/unsupported_feature.rb with error parse error | 2 |
| src/unsupported_feature.rb:3:7:3:7 | parse error | Extraction failed in src/unsupported_feature.rb with error parse error | 2 |
| src/unsupported_feature.rb:3:14:3:14 | parse error | Extraction failed in src/unsupported_feature.rb with error parse error | 2 |
| src/unsupported_feature.rb:3:1:3:8 | parse error | Extraction failed in src/unsupported_feature.rb with error parse error | 2 |

View File

@@ -11,6 +11,7 @@ edges
| impl/unsafeShell.rb:47:16:47:21 | target : | impl/unsafeShell.rb:48:19:48:27 | #{...} |
| impl/unsafeShell.rb:51:17:51:17 | x : | impl/unsafeShell.rb:52:14:52:14 | x |
| impl/unsafeShell.rb:51:17:51:17 | x : | impl/unsafeShell.rb:54:29:54:29 | x |
| impl/unsafeShell.rb:57:21:57:21 | x : | impl/unsafeShell.rb:58:23:58:23 | x |
nodes
| impl/sub/notImported.rb:2:12:2:17 | target : | semmle.label | target : |
| impl/sub/notImported.rb:3:19:3:27 | #{...} | semmle.label | #{...} |
@@ -35,6 +36,8 @@ nodes
| impl/unsafeShell.rb:51:17:51:17 | x : | semmle.label | x : |
| impl/unsafeShell.rb:52:14:52:14 | x | semmle.label | x |
| impl/unsafeShell.rb:54:29:54:29 | x | semmle.label | x |
| impl/unsafeShell.rb:57:21:57:21 | x : | semmle.label | x : |
| impl/unsafeShell.rb:58:23:58:23 | x | semmle.label | x |
subpaths
#select
| impl/sub/notImported.rb:3:14:3:28 | "cat #{...}" | impl/sub/notImported.rb:2:12:2:17 | target : | impl/sub/notImported.rb:3:19:3:27 | #{...} | This string construction which depends on $@ is later used in a $@. | impl/sub/notImported.rb:2:12:2:17 | target | library input | impl/sub/notImported.rb:3:5:3:34 | call to popen | shell command |
@@ -49,3 +52,4 @@ subpaths
| impl/unsafeShell.rb:48:14:48:28 | "cat #{...}" | impl/unsafeShell.rb:47:16:47:21 | target : | impl/unsafeShell.rb:48:19:48:27 | #{...} | This string construction which depends on $@ is later used in a $@. | impl/unsafeShell.rb:47:16:47:21 | target | library input | impl/unsafeShell.rb:48:5:48:34 | call to popen | shell command |
| impl/unsafeShell.rb:52:14:52:24 | call to join | impl/unsafeShell.rb:51:17:51:17 | x : | impl/unsafeShell.rb:52:14:52:14 | x | This array which depends on $@ is later used in a $@. | impl/unsafeShell.rb:51:17:51:17 | x | library input | impl/unsafeShell.rb:52:5:52:30 | call to popen | shell command |
| impl/unsafeShell.rb:54:14:54:40 | call to join | impl/unsafeShell.rb:51:17:51:17 | x : | impl/unsafeShell.rb:54:29:54:29 | x | This array which depends on $@ is later used in a $@. | impl/unsafeShell.rb:51:17:51:17 | x | library input | impl/unsafeShell.rb:54:5:54:46 | call to popen | shell command |
| impl/unsafeShell.rb:58:14:58:23 | ... + ... | impl/unsafeShell.rb:57:21:57:21 | x : | impl/unsafeShell.rb:58:23:58:23 | x | This string concatenation which depends on $@ is later used in a $@. | impl/unsafeShell.rb:57:21:57:21 | x | library input | impl/unsafeShell.rb:58:5:58:29 | call to popen | shell command |

View File

@@ -53,4 +53,8 @@ class Foobar2
IO.popen(["foo", "bar", x].join(' '), "w") # NOT OK
end
def string_concat(x)
IO.popen("cat " + x, "w") # NOT OK
end
end

View File

@@ -1,33 +1,38 @@
edges
| app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params : | app/controllers/foo/bars_controller.rb:9:12:9:29 | ...[...] : |
| app/controllers/foo/bars_controller.rb:9:12:9:29 | ...[...] : | app/views/foo/bars/show.html.erb:47:5:47:13 | call to user_name |
| app/controllers/foo/bars_controller.rb:9:12:9:29 | ...[...] : | app/views/foo/bars/show.html.erb:46:5:46:13 | call to user_name |
| app/controllers/foo/bars_controller.rb:13:5:13:14 | [post] self [@user_name] : | app/controllers/foo/bars_controller.rb:13:5:13:14 | [post] self [@user_name] : |
| app/controllers/foo/bars_controller.rb:13:5:13:14 | [post] self [@user_name] : | app/views/foo/bars/show.html.erb:51:5:51:18 | call to user_name_memo |
| app/controllers/foo/bars_controller.rb:13:5:13:14 | [post] self [@user_name] : | app/views/foo/bars/show.html.erb:50:5:50:18 | call to user_name_memo |
| app/controllers/foo/bars_controller.rb:13:20:13:25 | call to params : | app/controllers/foo/bars_controller.rb:13:20:13:37 | ...[...] : |
| app/controllers/foo/bars_controller.rb:13:20:13:37 | ...[...] : | app/controllers/foo/bars_controller.rb:13:5:13:14 | [post] self [@user_name] : |
| app/controllers/foo/bars_controller.rb:13:20:13:37 | ...[...] : | app/views/foo/bars/show.html.erb:51:5:51:18 | call to user_name_memo |
| app/controllers/foo/bars_controller.rb:13:20:13:37 | ...[...] : | app/views/foo/bars/show.html.erb:50:5:50:18 | call to user_name_memo |
| app/controllers/foo/bars_controller.rb:17:21:17:26 | call to params : | app/controllers/foo/bars_controller.rb:17:21:17:36 | ...[...] : |
| app/controllers/foo/bars_controller.rb:17:21:17:36 | ...[...] : | app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website |
| app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] : |
| app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] : | app/controllers/foo/bars_controller.rb:19:22:19:23 | dt : |
| app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] : | app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : |
| app/controllers/foo/bars_controller.rb:19:22:19:23 | dt : | app/views/foo/bars/show.html.erb:41:3:41:16 | @instance_text |
| app/controllers/foo/bars_controller.rb:19:22:19:23 | dt : | app/views/foo/bars/show.html.erb:40:3:40:16 | @instance_text |
| app/controllers/foo/bars_controller.rb:24:39:24:44 | call to params : | app/controllers/foo/bars_controller.rb:24:39:24:59 | ...[...] : |
| app/controllers/foo/bars_controller.rb:24:39:24:59 | ...[...] : | app/controllers/foo/bars_controller.rb:24:39:24:59 | ... = ... |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:44:76:44:87 | call to display_text : |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:8:9:8:21 | call to local_assigns [element :display_text] : |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:12:9:12:21 | call to local_assigns [element :display_text] : |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:17:15:17:27 | call to local_assigns [element :display_text] : |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:35:3:35:14 | call to display_text |
| app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | app/views/foo/bars/show.html.erb:43:76:43:87 | call to display_text : |
| app/controllers/foo/bars_controller.rb:30:11:30:16 | call to params : | app/controllers/foo/bars_controller.rb:30:11:30:28 | ...[...] : |
| app/controllers/foo/bars_controller.rb:30:11:30:28 | ...[...] : | app/controllers/foo/bars_controller.rb:31:5:31:7 | str |
| app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text |
| app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] |
| app/views/foo/bars/show.html.erb:44:76:44:87 | call to display_text : | app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : |
| app/views/foo/bars/show.html.erb:54:29:54:34 | call to params : | app/views/foo/bars/show.html.erb:54:29:54:44 | ...[...] |
| app/views/foo/bars/show.html.erb:57:13:57:18 | call to params : | app/views/foo/bars/show.html.erb:57:13:57:28 | ...[...] |
| app/views/foo/bars/show.html.erb:74:19:74:24 | call to params : | app/views/foo/bars/show.html.erb:74:19:74:34 | ...[...] |
| app/views/foo/bars/show.html.erb:77:28:77:33 | call to params : | app/views/foo/bars/show.html.erb:77:28:77:39 | ...[...] |
| app/views/foo/bars/_widget.html.erb:8:9:8:21 | call to local_assigns [element :display_text] : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] |
| app/views/foo/bars/show.html.erb:8:9:8:21 | call to local_assigns [element :display_text] : | app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] |
| app/views/foo/bars/show.html.erb:12:9:12:21 | call to local_assigns [element :display_text] : | app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] |
| app/views/foo/bars/show.html.erb:17:15:17:27 | call to local_assigns [element :display_text] : | app/views/foo/bars/show.html.erb:17:15:17:32 | ...[...] |
| app/views/foo/bars/show.html.erb:43:64:43:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text |
| app/views/foo/bars/show.html.erb:43:64:43:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:8:9:8:21 | call to local_assigns [element :display_text] : |
| app/views/foo/bars/show.html.erb:43:76:43:87 | call to display_text : | app/views/foo/bars/show.html.erb:43:64:43:87 | ... + ... : |
| app/views/foo/bars/show.html.erb:53:29:53:34 | call to params : | app/views/foo/bars/show.html.erb:53:29:53:44 | ...[...] |
| app/views/foo/bars/show.html.erb:56:13:56:18 | call to params : | app/views/foo/bars/show.html.erb:56:13:56:28 | ...[...] |
| app/views/foo/bars/show.html.erb:73:19:73:24 | call to params : | app/views/foo/bars/show.html.erb:73:19:73:34 | ...[...] |
| app/views/foo/bars/show.html.erb:76:28:76:33 | call to params : | app/views/foo/bars/show.html.erb:76:28:76:39 | ...[...] |
nodes
| app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params : | semmle.label | call to params : |
| app/controllers/foo/bars_controller.rb:9:12:9:29 | ...[...] : | semmle.label | ...[...] : |
@@ -47,25 +52,30 @@ nodes
| app/controllers/foo/bars_controller.rb:30:11:30:28 | ...[...] : | semmle.label | ...[...] : |
| app/controllers/foo/bars_controller.rb:31:5:31:7 | str | semmle.label | str |
| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | semmle.label | call to display_text |
| app/views/foo/bars/_widget.html.erb:8:9:8:21 | call to local_assigns [element :display_text] : | semmle.label | call to local_assigns [element :display_text] : |
| app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website | semmle.label | @user_website |
| app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text | semmle.label | call to display_text |
| app/views/foo/bars/show.html.erb:8:9:8:21 | call to local_assigns [element :display_text] : | semmle.label | call to local_assigns [element :display_text] : |
| app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:12:9:12:21 | call to local_assigns [element :display_text] : | semmle.label | call to local_assigns [element :display_text] : |
| app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text | semmle.label | call to display_text |
| app/views/foo/bars/show.html.erb:41:3:41:16 | @instance_text | semmle.label | @instance_text |
| app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : | semmle.label | ... + ... : |
| app/views/foo/bars/show.html.erb:44:76:44:87 | call to display_text : | semmle.label | call to display_text : |
| app/views/foo/bars/show.html.erb:47:5:47:13 | call to user_name | semmle.label | call to user_name |
| app/views/foo/bars/show.html.erb:51:5:51:18 | call to user_name_memo | semmle.label | call to user_name_memo |
| app/views/foo/bars/show.html.erb:54:29:54:34 | call to params : | semmle.label | call to params : |
| app/views/foo/bars/show.html.erb:54:29:54:44 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:57:13:57:18 | call to params : | semmle.label | call to params : |
| app/views/foo/bars/show.html.erb:57:13:57:28 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:74:19:74:24 | call to params : | semmle.label | call to params : |
| app/views/foo/bars/show.html.erb:74:19:74:34 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:77:28:77:33 | call to params : | semmle.label | call to params : |
| app/views/foo/bars/show.html.erb:77:28:77:39 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:17:15:17:27 | call to local_assigns [element :display_text] : | semmle.label | call to local_assigns [element :display_text] : |
| app/views/foo/bars/show.html.erb:17:15:17:32 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:35:3:35:14 | call to display_text | semmle.label | call to display_text |
| app/views/foo/bars/show.html.erb:40:3:40:16 | @instance_text | semmle.label | @instance_text |
| app/views/foo/bars/show.html.erb:43:64:43:87 | ... + ... : | semmle.label | ... + ... : |
| app/views/foo/bars/show.html.erb:43:76:43:87 | call to display_text : | semmle.label | call to display_text : |
| app/views/foo/bars/show.html.erb:46:5:46:13 | call to user_name | semmle.label | call to user_name |
| app/views/foo/bars/show.html.erb:50:5:50:18 | call to user_name_memo | semmle.label | call to user_name_memo |
| app/views/foo/bars/show.html.erb:53:29:53:34 | call to params : | semmle.label | call to params : |
| app/views/foo/bars/show.html.erb:53:29:53:44 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:56:13:56:18 | call to params : | semmle.label | call to params : |
| app/views/foo/bars/show.html.erb:56:13:56:28 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:73:19:73:24 | call to params : | semmle.label | call to params : |
| app/views/foo/bars/show.html.erb:73:19:73:34 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:76:28:76:33 | call to params : | semmle.label | call to params : |
| app/views/foo/bars/show.html.erb:76:28:76:39 | ...[...] | semmle.label | ...[...] |
subpaths
#select
| app/controllers/foo/bars_controller.rb:24:39:24:59 | ... = ... | app/controllers/foo/bars_controller.rb:24:39:24:44 | call to params : | app/controllers/foo/bars_controller.rb:24:39:24:59 | ... = ... | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:24:39:24:44 | call to params | user-provided value |
@@ -76,11 +86,12 @@ subpaths
| app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:41:3:41:16 | @instance_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:41:3:41:16 | @instance_text | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:47:5:47:13 | call to user_name | app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params : | app/views/foo/bars/show.html.erb:47:5:47:13 | call to user_name | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:51:5:51:18 | call to user_name_memo | app/controllers/foo/bars_controller.rb:13:20:13:25 | call to params : | app/views/foo/bars/show.html.erb:51:5:51:18 | call to user_name_memo | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:13:20:13:25 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:54:29:54:44 | ...[...] | app/views/foo/bars/show.html.erb:54:29:54:34 | call to params : | app/views/foo/bars/show.html.erb:54:29:54:44 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/views/foo/bars/show.html.erb:54:29:54:34 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:57:13:57:28 | ...[...] | app/views/foo/bars/show.html.erb:57:13:57:18 | call to params : | app/views/foo/bars/show.html.erb:57:13:57:28 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/views/foo/bars/show.html.erb:57:13:57:18 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:74:19:74:34 | ...[...] | app/views/foo/bars/show.html.erb:74:19:74:24 | call to params : | app/views/foo/bars/show.html.erb:74:19:74:34 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/views/foo/bars/show.html.erb:74:19:74:24 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:77:28:77:39 | ...[...] | app/views/foo/bars/show.html.erb:77:28:77:33 | call to params : | app/views/foo/bars/show.html.erb:77:28:77:39 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/views/foo/bars/show.html.erb:77:28:77:33 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:17:15:17:32 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:17:15:17:32 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:35:3:35:14 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:35:3:35:14 | call to display_text | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:40:3:40:16 | @instance_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:40:3:40:16 | @instance_text | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:46:5:46:13 | call to user_name | app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params : | app/views/foo/bars/show.html.erb:46:5:46:13 | call to user_name | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:50:5:50:18 | call to user_name_memo | app/controllers/foo/bars_controller.rb:13:20:13:25 | call to params : | app/views/foo/bars/show.html.erb:50:5:50:18 | call to user_name_memo | Cross-site scripting vulnerability due to a $@. | app/controllers/foo/bars_controller.rb:13:20:13:25 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:53:29:53:44 | ...[...] | app/views/foo/bars/show.html.erb:53:29:53:34 | call to params : | app/views/foo/bars/show.html.erb:53:29:53:44 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/views/foo/bars/show.html.erb:53:29:53:34 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:56:13:56:28 | ...[...] | app/views/foo/bars/show.html.erb:56:13:56:18 | call to params : | app/views/foo/bars/show.html.erb:56:13:56:28 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/views/foo/bars/show.html.erb:56:13:56:18 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:73:19:73:34 | ...[...] | app/views/foo/bars/show.html.erb:73:19:73:24 | call to params : | app/views/foo/bars/show.html.erb:73:19:73:34 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/views/foo/bars/show.html.erb:73:19:73:24 | call to params | user-provided value |
| app/views/foo/bars/show.html.erb:76:28:76:39 | ...[...] | app/views/foo/bars/show.html.erb:76:28:76:33 | call to params : | app/views/foo/bars/show.html.erb:76:28:76:39 | ...[...] | Cross-site scripting vulnerability due to a $@. | app/views/foo/bars/show.html.erb:76:28:76:33 | call to params | user-provided value |

View File

@@ -1,39 +1,49 @@
edges
| app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/controllers/foo/stores_controller.rb:9:22:9:23 | dt : |
| app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : |
| app/controllers/foo/stores_controller.rb:9:22:9:23 | dt : | app/views/foo/stores/show.html.erb:38:3:38:16 | @instance_text |
| app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name : | app/views/foo/stores/show.html.erb:83:5:83:24 | @other_user_raw_name |
| app/controllers/foo/stores_controller.rb:9:22:9:23 | dt : | app/views/foo/stores/show.html.erb:37:3:37:16 | @instance_text |
| app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name : | app/views/foo/stores/show.html.erb:82:5:82:24 | @other_user_raw_name |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:5:9:5:36 | ...[...] |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:9:9:9:26 | ...[...] |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:33:3:33:14 | call to display_text |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:41:76:41:87 | call to display_text : |
| app/views/foo/stores/show.html.erb:41:64:41:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text |
| app/views/foo/stores/show.html.erb:41:64:41:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] |
| app/views/foo/stores/show.html.erb:41:76:41:87 | call to display_text : | app/views/foo/stores/show.html.erb:41:64:41:87 | ... + ... : |
| app/views/foo/stores/show.html.erb:87:17:87:28 | call to handle : | app/views/foo/stores/show.html.erb:87:3:87:29 | call to sprintf |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:5:9:5:21 | call to local_assigns [element :display_text] : |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:9:9:9:21 | call to local_assigns [element :display_text] : |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:14:15:14:27 | call to local_assigns [element :display_text] : |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:32:3:32:14 | call to display_text |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | app/views/foo/stores/show.html.erb:40:76:40:87 | call to display_text : |
| app/views/foo/bars/_widget.html.erb:8:9:8:21 | call to local_assigns [element :display_text] : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] |
| app/views/foo/stores/show.html.erb:5:9:5:21 | call to local_assigns [element :display_text] : | app/views/foo/stores/show.html.erb:5:9:5:36 | ...[...] |
| app/views/foo/stores/show.html.erb:9:9:9:21 | call to local_assigns [element :display_text] : | app/views/foo/stores/show.html.erb:9:9:9:26 | ...[...] |
| app/views/foo/stores/show.html.erb:14:15:14:27 | call to local_assigns [element :display_text] : | app/views/foo/stores/show.html.erb:14:15:14:32 | ...[...] |
| app/views/foo/stores/show.html.erb:40:64:40:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text |
| app/views/foo/stores/show.html.erb:40:64:40:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:8:9:8:21 | call to local_assigns [element :display_text] : |
| app/views/foo/stores/show.html.erb:40:76:40:87 | call to display_text : | app/views/foo/stores/show.html.erb:40:64:40:87 | ... + ... : |
| app/views/foo/stores/show.html.erb:86:17:86:28 | call to handle : | app/views/foo/stores/show.html.erb:86:3:86:29 | call to sprintf |
nodes
| app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | semmle.label | call to read : |
| app/controllers/foo/stores_controller.rb:9:22:9:23 | dt : | semmle.label | dt : |
| app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name : | semmle.label | call to raw_name : |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | semmle.label | dt : |
| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | semmle.label | call to display_text |
| app/views/foo/bars/_widget.html.erb:8:9:8:21 | call to local_assigns [element :display_text] : | semmle.label | call to local_assigns [element :display_text] : |
| app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | semmle.label | ...[...] |
| app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text | semmle.label | call to display_text |
| app/views/foo/stores/show.html.erb:5:9:5:21 | call to local_assigns [element :display_text] : | semmle.label | call to local_assigns [element :display_text] : |
| app/views/foo/stores/show.html.erb:5:9:5:36 | ...[...] | semmle.label | ...[...] |
| app/views/foo/stores/show.html.erb:9:9:9:21 | call to local_assigns [element :display_text] : | semmle.label | call to local_assigns [element :display_text] : |
| app/views/foo/stores/show.html.erb:9:9:9:26 | ...[...] | semmle.label | ...[...] |
| app/views/foo/stores/show.html.erb:33:3:33:14 | call to display_text | semmle.label | call to display_text |
| app/views/foo/stores/show.html.erb:38:3:38:16 | @instance_text | semmle.label | @instance_text |
| app/views/foo/stores/show.html.erb:41:64:41:87 | ... + ... : | semmle.label | ... + ... : |
| app/views/foo/stores/show.html.erb:41:76:41:87 | call to display_text : | semmle.label | call to display_text : |
| app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | semmle.label | call to handle |
| app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | semmle.label | call to raw_name |
| app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | semmle.label | call to handle |
| app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | semmle.label | call to raw_name |
| app/views/foo/stores/show.html.erb:80:5:80:22 | call to display_name | semmle.label | call to display_name |
| app/views/foo/stores/show.html.erb:83:5:83:24 | @other_user_raw_name | semmle.label | @other_user_raw_name |
| app/views/foo/stores/show.html.erb:87:3:87:29 | call to sprintf | semmle.label | call to sprintf |
| app/views/foo/stores/show.html.erb:87:17:87:28 | call to handle : | semmle.label | call to handle : |
| app/views/foo/stores/show.html.erb:14:15:14:27 | call to local_assigns [element :display_text] : | semmle.label | call to local_assigns [element :display_text] : |
| app/views/foo/stores/show.html.erb:14:15:14:32 | ...[...] | semmle.label | ...[...] |
| app/views/foo/stores/show.html.erb:32:3:32:14 | call to display_text | semmle.label | call to display_text |
| app/views/foo/stores/show.html.erb:37:3:37:16 | @instance_text | semmle.label | @instance_text |
| app/views/foo/stores/show.html.erb:40:64:40:87 | ... + ... : | semmle.label | ... + ... : |
| app/views/foo/stores/show.html.erb:40:76:40:87 | call to display_text : | semmle.label | call to display_text : |
| app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | semmle.label | call to handle |
| app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | semmle.label | call to raw_name |
| app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | semmle.label | call to handle |
| app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | semmle.label | call to raw_name |
| app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | semmle.label | call to display_name |
| app/views/foo/stores/show.html.erb:82:5:82:24 | @other_user_raw_name | semmle.label | @other_user_raw_name |
| app/views/foo/stores/show.html.erb:86:3:86:29 | call to sprintf | semmle.label | call to sprintf |
| app/views/foo/stores/show.html.erb:86:17:86:28 | call to handle : | semmle.label | call to handle : |
subpaths
#select
| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
@@ -41,12 +51,13 @@ subpaths
| app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:5:9:5:36 | ...[...] | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:5:9:5:36 | ...[...] | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:9:9:9:26 | ...[...] | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:9:9:9:26 | ...[...] | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:33:3:33:14 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:33:3:33:14 | call to display_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:38:3:38:16 | @instance_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:38:3:38:16 | @instance_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | stored value |
| app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | stored value |
| app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | stored value |
| app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | stored value |
| app/views/foo/stores/show.html.erb:80:5:80:22 | call to display_name | app/views/foo/stores/show.html.erb:80:5:80:22 | call to display_name | app/views/foo/stores/show.html.erb:80:5:80:22 | call to display_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:80:5:80:22 | call to display_name | stored value |
| app/views/foo/stores/show.html.erb:83:5:83:24 | @other_user_raw_name | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name : | app/views/foo/stores/show.html.erb:83:5:83:24 | @other_user_raw_name | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name | stored value |
| app/views/foo/stores/show.html.erb:87:3:87:29 | call to sprintf | app/views/foo/stores/show.html.erb:87:17:87:28 | call to handle : | app/views/foo/stores/show.html.erb:87:3:87:29 | call to sprintf | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:87:17:87:28 | call to handle | stored value |
| app/views/foo/stores/show.html.erb:14:15:14:32 | ...[...] | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:14:15:14:32 | ...[...] | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:32:3:32:14 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:32:3:32:14 | call to display_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:37:3:37:16 | @instance_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:37:3:37:16 | @instance_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value |
| app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:46:5:46:16 | call to handle | stored value |
| app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:49:5:49:18 | call to raw_name | stored value |
| app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:63:3:63:18 | call to handle | stored value |
| app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:69:3:69:20 | call to raw_name | stored value |
| app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:79:5:79:22 | call to display_name | stored value |
| app/views/foo/stores/show.html.erb:82:5:82:24 | @other_user_raw_name | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name : | app/views/foo/stores/show.html.erb:82:5:82:24 | @other_user_raw_name | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name | stored value |
| app/views/foo/stores/show.html.erb:86:3:86:29 | call to sprintf | app/views/foo/stores/show.html.erb:86:17:86:28 | call to handle : | app/views/foo/stores/show.html.erb:86:3:86:29 | call to sprintf | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:86:17:86:28 | call to handle | stored value |

View File

@@ -0,0 +1,16 @@
edges
| lib/unsafeHtml.rb:2:31:2:34 | name : | lib/unsafeHtml.rb:3:10:3:16 | #{...} |
| lib/unsafeHtml.rb:9:27:9:30 | name : | lib/unsafeHtml.rb:11:13:11:19 | #{...} |
| lib/unsafeHtml.rb:16:19:16:22 | name : | lib/unsafeHtml.rb:17:28:17:31 | name |
nodes
| lib/unsafeHtml.rb:2:31:2:34 | name : | semmle.label | name : |
| lib/unsafeHtml.rb:3:10:3:16 | #{...} | semmle.label | #{...} |
| lib/unsafeHtml.rb:9:27:9:30 | name : | semmle.label | name : |
| lib/unsafeHtml.rb:11:13:11:19 | #{...} | semmle.label | #{...} |
| lib/unsafeHtml.rb:16:19:16:22 | name : | semmle.label | name : |
| lib/unsafeHtml.rb:17:28:17:31 | name | semmle.label | name |
subpaths
#select
| lib/unsafeHtml.rb:3:10:3:16 | #{...} | lib/unsafeHtml.rb:2:31:2:34 | name : | lib/unsafeHtml.rb:3:10:3:16 | #{...} | This string interpolation which depends on $@ might later allow $@. | lib/unsafeHtml.rb:2:31:2:34 | name | library input | lib/unsafeHtml.rb:3:5:3:22 | "<h2>#{...}</h2>" | cross-site scripting |
| lib/unsafeHtml.rb:11:13:11:19 | #{...} | lib/unsafeHtml.rb:9:27:9:30 | name : | lib/unsafeHtml.rb:11:13:11:19 | #{...} | This string interpolation which depends on $@ might later allow $@. | lib/unsafeHtml.rb:9:27:9:30 | name | library input | lib/unsafeHtml.rb:13:5:13:5 | h | cross-site scripting |
| lib/unsafeHtml.rb:17:28:17:31 | name | lib/unsafeHtml.rb:16:19:16:22 | name : | lib/unsafeHtml.rb:17:28:17:31 | name | This string format which depends on $@ might later allow $@. | lib/unsafeHtml.rb:16:19:16:22 | name | library input | lib/unsafeHtml.rb:17:5:17:32 | call to sprintf | cross-site scripting |

View File

@@ -0,0 +1 @@
queries/security/cwe-079/UnsafeHtmlConstruction.ql

View File

@@ -14,7 +14,6 @@
<ul>
<% for key in [:display_text, :safe_text] do %>
<%# BAD: A local rendered raw via the locals hash %>
<%# TODO: we miss that `key` can take `:display_text` as a value here %>
<li><%= raw local_assigns[key] %></li>
<% end %>
</ul>

View File

@@ -11,7 +11,6 @@
<ul>
<% for key in [:display_text, :safe_text] do %>
<%# BAD: A local rendered raw via the locals hash %>
<%# TODO: we miss that `key` can take `:display_text` as a value here %>
<li><%= raw local_assigns[key] %></li>
<% end %>
</ul>
@@ -88,4 +87,4 @@
%>
<%# GOOD: The `foo.bar.baz` is not recognized as a source %>
<%= @other_user_raw_name.foo.bar.baz.html_safe %>
<%= @other_user_raw_name.foo.bar.baz.html_safe %>

View File

@@ -0,0 +1,22 @@
class Foobar
def create_user_description(name)
"<h2>#{name}</h2>".html_safe # NOT OK - the parameter is not escaped
# escape
"<h2>#{ERB::Util.html_escape(name)}</h2>".html_safe # OK - the parameter is escaped
end
def string_like_literal name
h = <<-HTML
<h2>#{name}</h2>
HTML
h.html_safe # NOT OK - the parameter is not escaped
end
def sprintf_use name
sprintf("<h2>%s</h2>", name).html_safe # NOT OK - the parameter is not escaped
# escape
sprintf("<h2>%s</h2>", ERB::Util.html_escape(name)).html_safe # OK - the parameter is escaped
end
end

View File

@@ -0,0 +1,5 @@
Gem::Specification.new do |s|
s.name = 'unsafe-html'
s.require_path = "lib"
end

Some files were not shown because too many files have changed in this diff Show More