mirror of
https://github.com/github/codeql.git
synced 2026-05-03 04:39:29 +02:00
Merge branch 'main' into json-log
This commit is contained in:
BIN
ruby/Cargo.lock
generated
BIN
ruby/Cargo.lock
generated
Binary file not shown.
@@ -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
@@ -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
|
||||
@@ -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"] }
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.5.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.5.0
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
@@ -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.
|
||||
4
ruby/ql/lib/change-notes/2023-01-12-rack.md
Normal file
4
ruby/ql/lib/change-notes/2023-01-12-rack.md
Normal 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.
|
||||
@@ -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.
|
||||
3
ruby/ql/lib/change-notes/released/0.5.1.md
Normal file
3
ruby/ql/lib/change-notes/released/0.5.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.5.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.5.0
|
||||
lastReleaseVersion: 0.5.1
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = "**" }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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[]" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
48
ruby/ql/lib/codeql/ruby/frameworks/Rack.qll
Normal file
48
ruby/ql/lib/codeql/ruby/frameworks/Rack.qll
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(_)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
}
|
||||
@@ -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(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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" }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `rb/unsafe-deserialization` query now recognizes input from STDIN as a source.
|
||||
9
ruby/ql/src/change-notes/released/0.5.1.md
Normal file
9
ruby/ql/src/change-notes/released/0.5.1.md
Normal 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.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.5.0
|
||||
lastReleaseVersion: 0.5.1
|
||||
|
||||
4
ruby/ql/src/codeql-suites/ruby-security-experimental.qls
Normal file
4
ruby/ql/src/codeql-suites/ruby-security-experimental.qls
Normal file
@@ -0,0 +1,4 @@
|
||||
- description: Extended and experimental security queries for Ruby
|
||||
- queries: .
|
||||
- apply: security-experimental-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
@@ -7,6 +7,7 @@
|
||||
* @precision medium
|
||||
* @id rb/user-controlled-bypass
|
||||
* @tags security
|
||||
* experimental
|
||||
* external/cwe/cwe-807
|
||||
* external/cwe/cwe-290
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* @problem.severity warning
|
||||
* @precision high
|
||||
* @tags security
|
||||
* experimental
|
||||
* @id rb/improper-memoization
|
||||
*/
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @precision low
|
||||
* @id rb/manually-checking-http-verb
|
||||
* @tags security
|
||||
* experimental
|
||||
*/
|
||||
|
||||
import codeql.ruby.AST
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @precision medium
|
||||
* @id rb/weak-params
|
||||
* @tags security
|
||||
* experimental
|
||||
*/
|
||||
|
||||
import codeql.ruby.AST
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/ruby-queries
|
||||
version: 0.5.1-dev
|
||||
version: 0.5.2-dev
|
||||
groups:
|
||||
- ruby
|
||||
- queries
|
||||
|
||||
@@ -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><b></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>
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
@@ -0,0 +1,10 @@
|
||||
module MyLib
|
||||
def unsafeDeserialize(value)
|
||||
eval("foo = #{value}")
|
||||
foo
|
||||
end
|
||||
|
||||
def unsafeGetter(obj, path)
|
||||
eval("obj.#{path}")
|
||||
end
|
||||
end
|
||||
@@ -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}"
|
||||
@@ -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}"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
4
ruby/ql/test/library-tests/frameworks/rack/Rack.expected
Normal file
4
ruby/ql/test/library-tests/frameworks/rack/Rack.expected
Normal 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 |
|
||||
4
ruby/ql/test/library-tests/frameworks/rack/Rack.ql
Normal file
4
ruby/ql/test/library-tests/frameworks/rack/Rack.ql
Normal 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() }
|
||||
61
ruby/ql/test/library-tests/frameworks/rack/rack.rb
Normal file
61
ruby/ql/test/library-tests/frameworks/rack/rack.rb
Normal 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
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
@@ -0,0 +1 @@
|
||||
queries/security/cwe-079/UnsafeHtmlConstruction.ql
|
||||
@@ -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>
|
||||
|
||||
@@ -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 %>
|
||||
|
||||
22
ruby/ql/test/query-tests/security/cwe-079/lib/unsafeHtml.rb
Normal file
22
ruby/ql/test/query-tests/security/cwe-079/lib/unsafeHtml.rb
Normal 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
|
||||
@@ -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
Reference in New Issue
Block a user